Elasticsearch sort exact matches and fuzzy matches in different sets

Viewed 156

This is my first ever question here so I apologize if I make any mistakes.

I'm trying to make a fuzzy search (match query with fuzziness parameter) on my index that will return the results in Alphabetical order. But I need the exact matches to come first(Alphabetically ordered among themselves) and fuzzy matches later.

I have tried this to make exact matches have higher scores. But they are just being sorted by their scores:

   "query":{
      "bool":{
         "must":[
            {
               "match":{
                  "myPropertyName":{
                     "query":"myWord",
                     "fuzziness":"AUTO"
                  }
               }
            }
         ],
         "should":[
            {
               "match":{
                  "myPropertyName":{
                     "query":"myWord",
                     "boost":20
                  }
               }
            }
         ]
      }
   },
   "sort":[
      "_score",
      {
         "myProperty.keyword":{
            "order":"asc"
         }
      }
   ],
   "track_scores":true
}

Then I have tried to make the scores of all exact matches and fuzzy matches same among themselves with many methods. I can make it for fuzzy matches by using filter or constant_score but I couldn't figure a way to assign a custom score to the results of should query in my search.

How can I achieve this?

1 Answers

I've managed to achieve this by using a function score query with "boost_mode": "replace" and setting a custom value to weight parameter like: "weight": "10".

{
   "query":{
      "function_score":{
         "query":{
            "bool":{
               "filter":[
                  {
                     "match":{
                        "myPropertyName":{
                           "query":"myWord",
                           "fuzziness":"AUTO"
                        }
                     }
                  }
               ]
            }
         },
         "boost_mode":"replace",
         "functions":[
            {
               "filter":{
                  "match":{
                     "myPropertyName":{
                        "query":"myWord"
                     }
                  }
               },
               "weight":"10"
            }
         ]
      }
   },
   "sort":[
      "_score",
      {
         "myProperty.keyword":{
            "order":"asc"
         }
      }
   ],
   "track_scores":true
}

This way documents that match the match query will return with 0 score since it's also a filter query. Then among these documents the ones that match the function will return with 10 score since "boost_mode": "replace" and "weight: "10".

When it comes to sorting firstly Elasticsearch will sort the results by their score's since it comes first in "sort[]" array. Then documents with same scores will be sorted alphabetically among themselves.

This worked perfectly for me.

Related