Search Non Indexed Text Field in Elasticsearch

Table of Contents

1. Introduction

Recently I got request for help with querying for documents having fields equal to specific value. Customer had issue because query was resulting empty page.

After quick analyses, field turn out to be non indexed. 

				
					      "color": {
        "type": "text",
        "index": false
      }
				
			

So that was the reason why she couldn’t find it. Fortunately there is solution for such cases. In this knowledge article I want to explain you how to deal with such scenarios and have right results.

2. Start Elasticsearch Cluster

Start Elasticsearch and Kibana using project from my article. 

3. Load test data

Run below in Kibana Dev Tools

				
					PUT /apples
{
  "mappings": {
    "properties": {
      "apple_name": {
        "type": "keyword"
      },
      "color": {
        "type": "text",
        "index": false
      }
    }
  }
}

POST /apples/_bulk
{ "index": { "_id": 1 } }
{ "apple_name": "Granny Smith", "color": "green" }
{ "index": { "_id": 2 } }
{ "apple_name": "Red Delicious", "color": "red" }
{ "index": { "_id": 3 } }
{ "apple_name": "Golden Delicious", "color": "yellow" }
{ "index": { "_id": 4 } }
{ "apple_name": "Fuji", "color": "red" }
{ "index": { "_id": 5 } }
{ "apple_name": "Pink Lady", "color": "pink" }
				
			

4. Solution

4.1. Painless Runtime Field

for temporary solution use painless to create runtime field in search request

				
					GET /apples/_search
{
  "runtime_mappings": {
    "is_red": {
      "type": "boolean",
      "script": {
        "source": "emit(params._source.color == 'red')"
      }
    }
  },
  "query": {
    "term": {
      "is_red": true
    }
  },
  "_source": ["apple_name", "color"],
  "size": 10
}
				
			

In case of nested fields like array of colors you can also handle that, although it is not case of this example.

				
					"source": """
  if (params._source.colors != null && params._source.colors.size() > 0) {
    emit(params._source.colors[0].color == 'red');
  } else {
    emit(false);
  }
"""
				
			

4.2. Reindex data

Reindex the entire index with an updated mapping that indexes previously non-indexed fields. That’s the cleanest, most scalable, and production-grade solution.

This gives you:

  • Full querying power on the field (e.g., term, match, range)
  • No need for scripts
  • Performance improvements (due to field-level indexing)
  • Cleaner architecture for future analytics or filtering

4.2.1. Create New Mapping Definition

				
					PUT /apples_v2
{
  "mappings": {
    "properties": {
      "apple_name": {
        "type": "keyword"
      },
      "color": {
        "type": "text"
      }
    }
  }
}
				
			

4.2.2. reindex

				
					POST _reindex
{
  "source": {
    "index": "apples"
  },
  "dest": {
    "index": "apples_v2"
  }
}
				
			

If your application uses an alias, just switch it:

				
					POST _aliases
{
  "actions": [
    { "remove": { "index": "apples", "alias": "apples_alias" }},
    { "add":    { "index": "apples_v2", "alias": "apples_alias" }}
  ]
}
				
			

5. Final thoughts

In this knowledge article you have learned how to search for documents by non indexed text field. Now you are not afraid of errors like

				
					"reason": {
          "type": "query_shard_exception",
          "reason": "failed to create query: Cannot search on field [color] since it is not indexed.",
				
			

Important to mention that if field type is keyword

				
					      "color": {
        "type": "keyword",
        "index": false
      }
				
			

Then Elasticsearch will fallback to doc_values, columnar formatted on-disk data structure. So you will not have issue like with text data type.

Have a nice coding!

Leave a Reply

Your email address will not be published. Required fields are marked *

Follow me on LinkedIn
Share the Post:

Enjoy Free Useful Amazing Content

Related Posts