somethingyouwant
somethingyouwant

Reputation: 171

Elasticsearch - How to list exact match at the top

I am searching the word "Adana" in Elasticsearch and want it to come at top because it is the exact word, but it doesn't.

Instead "Bilmemne Adana Otel" comes at top.

Normal query doesn't do any good so I tried the boolean query with "must" and "should". But it doesn't change anything too.

In addition to that, if i write "Ada" the "Adana" should come first too.

How can we make it work right?

Query:

curl -X GET "localhost:9200/destinations/_search" -H 'Content-Type: 
application/json' -d'
{
 "query": {
   "match": {
     “Name”: {
       "query": “Adana”
      }
    }
  }
}
'

Result:

{
"took" : 16,
"timed_out" : false,
"_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
},
"hits" : {
    "total" : 3,
    "max_score" : 3.255435,
    "hits" : [
    {
        "_index" : "destinations",
        "_type" : "_doc",
        "_id" : "10",
        "_score" : 3.255435,
        "_source" : {
        "name" : "Bilmemne Adana Otel"
        }
    },
    {
        "_index" : "destinations",
        "_type" : "_doc",
        "_id" : "4",
        "_score" : 2.8624198,
        "_source" : {
        "name" : "Adana"
        }
    },
    {
        "_index" : "destinations",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 2.3216834,
        "_source" : {
        "name" : "Adana Airport Otel - Adana"
        }
    }
    ]
}
}

Index:

{
"settings": {
    "analysis": {
    "filter": {
        "autocomplete_filter": {
        "type": "edge_ngram",
        "min_gram": 2,
        "max_gram": 15
        }
    },
    "analyzer": {
        "autocomplete": { 
        "type": "custom",
        "tokenizer": "standard",
        "filter": [
            "lowercase",
            "autocomplete_filter"
        ]
        }
    }
    }
},
"mappings": {
    "_doc": {
    "properties": {
        "name": {
        "type": "text",
        "analyzer": "autocomplete", 
        "search_analyzer": "standard" 
        }
    }
    }
}
}

Upvotes: 5

Views: 1386

Answers (1)

Tim
Tim

Reputation: 1286

If you want your exact matches to be on top, you could use a keyword field in your mapping.

{
  "settings": {
    "analysis": {
      "filter": {
        "autocomplete_filter": {
          "type": "edge_ngram",
          "min_gram": 3,
          "max_gram": 15
        }
      },
      "analyzer": {
        "autocomplete": {
          "type": "custom",
          "tokenizer": "standard",
          "filter": [
            "lowercase",
            "autocomplete_filter"
          ]
        }
      }
    }
  },
  "mappings": {
    "_doc": {
      "properties": {
        "name": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword"
            }
          },
          "analyzer": "autocomplete",
          "search_analyzer": "standard"
        }
      }
    }
  }
}

Then you can have a bool query that uses your keyword in the should query.

{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "Adana"
          }
        }
      ],
      "should": [
        {
          "term": {
            "name.keyword": {
              "value": "Adana"
            }
          }
        }
      ]
    }
  }
}

That should push the exact match to the top.

Upvotes: 3

Related Questions