Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elastic Search Hyphen issue with term filter

People also ask

How do you find a hyphen in Elasticsearch?

Imagine that you have "m0-77", "m1-77" and "m2-77", if you search m*-77 you are going to have zero hits. However you can remplace "-" (hyphen) with AND in order to connect the two separed words and then search m* AND 77 that is going to give you a correct hit. you can do it in the client front.

What is difference between term and terms in Elasticsearch?

Term query return documents that contain one or more exact term in a provided field. The terms query is the same as the term query, except you can search for multiple values. Warning: Avoid using the term query for text fields.

What are term based search queries in Elasticsearch?

You can use the term query to find documents based on a precise value such as a price, a product ID, or a username. Avoid using the term query for text fields. By default, Elasticsearch changes the values of text fields as part of analysis. This can make finding exact matches for text field values difficult.


I would guess that your field is analyzed, which is default setting for string fields in elasticsearch. As a result, when it indexed it's not indexed as one term "update-time" but instead as 2 terms: "update" and "time". That's why your term search cannot find this term. If your field will always contain values that will have to be matched completely as is, it would be the best to define such field in mapping as not analyzed. You can do it by recreating the index with new mapping:

curl -XPUT http://localhost:9200/your-index -d '{
    "mappings" : {
        "your-type" : {
            "properties" : {
                "field" : { "type": "string", "index" : "not_analyzed" }
            }
        }
    }
}'

curl -XPUT  http://localhost:9200/your-index/your-type/1 -d '{
    "field" : "update-time"
}'

curl -XPOST http://localhost:9200/your-index/your-type/_search -d'{
    "filter": {
        "term": {
                "field": "update-time"
        }
    }
}'

Alternatively, if you want some flexibility in finding records based on this field, you can keep this field analyzed and use text queries instead:

curl -XPOST http://localhost:9200/your-index/your-type/_search -d'{
    "query": {
        "text": {
                "field": "update-time"
        }
    }
}'

Please, keep in mind that if your field is analyzed then this record will be found by searching for just word "update" or word "time" as well.


The accepted answer didn't work for me with elastic 6.1. I solved it using the "keyword" field that elastic provides by default on string fields.

{
    "filter": {
            "term": {
                    "field.keyword": "update-time"
                }
        }
}

Based on the answer by @imotov If you're using spring-data-elasticsearch then all you need to do is mark your field as:

@Field(type = FieldType.String, index = FieldIndex.not_analyzed)

instead of

@Field(type = FieldType.String)

The problem is you need to drop the index though and re-instantiate it with new mappings.