sveatlo
sveatlo

Reputation: 593

Elasticsearch: prefer prefix match over term match

I've got a field in elasticsearch index, in which I'm trying to search and I'd like for the documents where this field's value begins with the search term to be higher up than documents, where the term is somewhere in the middle of a long phrase. E.g.: When searching for "lorem",

{
  "title": "Lorem"
}

should have higher score than

{
  "title": "The time I said Lorem"
}

or

{
  "title": "The Lorem"
}

or even

{
  "title": "Lorem impsum"
}

However this is often not the case with a simple match, match_phrase_prefix or query_string query.

So far I've tried combining prefix query with a match query while boosting the prefix, but the boosting doesn't seem to work as I expected, i.e. the results are the same just boosted by 10

...
{
    "should": [
        {
            "prefix": {
                "title": {
                    "value": query,
                    "boost": 10
                }
            }
        }
        {
            "match": {
                "title": {
                    "query":     query,
                    "boost":     3,
                    "fuzziness": "AUTO"
                }
            }
        }
    ]
}
...

Also, not sure if this is relevant, but the title field is actually nested, i.e. it's alternative_names.title

Is there any elegant solution to this with elasticsearch?

Upvotes: 0

Views: 626

Answers (1)

Bhavya
Bhavya

Reputation: 16172

You can use a combination bool/should clause to achieve your required results.

Adding a working example

Index Mapping:

{
  "mappings": {
    "properties": {
      "alternative_names": {
        "type": "nested",
        "properties": {
          "title": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword"
              }
            }
          }
        }
      }
    }
  }
}

Index data:

{
  "alternative_names": {
    "title": "Lorem"
  }
}
{
  "alternative_names": {
    "title": "The time I said Lorem"
  }
}
{
  "alternative_names": {
    "title": "The Lorem"
  }
}
{
  "alternative_names": {
    "title": "Lorem impsum"
  }
}

Search Query:

{
  "query": {
    "nested": {
      "path": "alternative_names",
      "query": {
        "bool": {
          "should": [
            {
              "term": {
                "alternative_names.title.keyword": "Lorem"
              }
            },
            {
              "match": {
                "alternative_names.title": "Lorem"
              }
            }
          ]
        }
      }
    }
  }
}

Search Result:

"hits": [
      {
        "_index": "66500753",
        "_type": "_doc",
        "_id": "1", 
        "_score": 1.3436072,
        "_source": {
          "alternative_names": {          // note this
            "title": "Lorem"
          }
        }
      },
      {
        "_index": "66500753",
        "_type": "_doc",
        "_id": "4",
        "_score": 0.11474907,
        "_source": {
          "alternative_names": {
            "title": "Lorem impsum"
          }
        }
      },
      {
        "_index": "66500753",
        "_type": "_doc",
        "_id": "3",
        "_score": 0.11474907,
        "_source": {
          "alternative_names": {
            "title": "The Lorem"
          }
        }
      },
      {
        "_index": "66500753",
        "_type": "_doc",
        "_id": "2",
        "_score": 0.07477197,
        "_source": {
          "alternative_names": {
            "title": "The time I said Lorem"
          }
        }
      }
    ]

Upvotes: 1

Related Questions