Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elasticsearch return exact match first then other matches

I have some PageDocuments which I would like to search based on the title, excluding PageDocuments with a path starting with some particular text. This field is analyzed. I would like some fuzziness to help users with spelling mistakes. I need to be able to do partial matches so some would match some text and this is some text.

If I use the following query I don't get an exact match back as the first result because of tf-idf

{
  "size": 20,
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "title": {
              "query": "myterm",
              "fuzziness": 1
            }
          }
        }
      ],
      "must_not": [
        {
          "wildcard": {
            "path": {
              "value": "/test/*"
            }
          }
        }
      ]
    }
  }
}

So then I added a not_analyzed version of the title field at title.not_analyzed and tried adding a function score to increase the weighting of an exact match using term.

{
  "query": {
    "function_score": {
      "functions": [
        {
          "weight": 2,
          "filter": {
            "fquery": {
              "query": {
                "term": {
                  "title.not_analyzed": {
                    "value": "myterm"
                  }
                }
              }
            }
          }
        }
      ],
      "query": {
        "bool": {
          "must": [
            {
              "match": {
                "title": {
                  "query": "myterm",
                  "fuzziness": 1
                }
              }
            }
          ],
          "must_not": [
            {
              "wildcard": {
                "path": {
                  "value": "/path/*"
                }
              }
            }
          ]
        }
      },
      "boost_mode": "multiply"
    }
  }
}

But this gives me the same results. How can I get the exact matches returned first?

like image 680
Jim Jeffries Avatar asked Mar 10 '23 01:03

Jim Jeffries


1 Answers

We found a solution to this by adding a combination of should and boost.

{
  "size": 20,
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "title": {
              "query": "myterm",
              "fuzziness": 1
            }
          }
        }
      ],
      "must_not": [
        {
          "wildcard": {
            "path": {
              "value": "/path/*"
            }
          }
        }
      ],
      "should": [
        {
          "term": {
            "title": {
              "value": "myterm",
              "boost": 10
            }
          }
        }
      ]
    }
  }
}
like image 70
Jim Jeffries Avatar answered Apr 27 '23 16:04

Jim Jeffries