
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!