1

Let's say I have these documents in Elasticsearch:

{
    "display_name": "Jose Cummings",
    "username": "josecummings"
},
{
    "display_name": "Jose Ramirez",
    "username": "elite_gamer"
},
{
    "display_name": "Lance Abrams",
    "username": "abrams1"
},
{
    "display_name": "Steve Smith",
    "username": "josesmose"
}

I want to run a "as you type" search for Jose that searches against both the display_name and the username fields, which I can do with this:

{
    "query": {
        "bool": {
            "must": {
                "multi_match": {
                    "fields": [
                        "display_name",
                        "username"
                    ],
                    "query": "Jose",
                    "type": "bool_prefix",
                    "fuzziness": "AUTO",
                    "boost": 50
                }
            }
        }
    }
}

The issue here is that when I search for Jose, Jose Cummings gets 100 points while Jose Ramirez and Steve Smith only get 50 points, because it seems to sum the scores for the two fields. This essentially rewards a user for having the same display_name as username, which we do not want to happen.

Is there a way to only take the max score from the two fields? I've tried dozens of different combinations now using function_score, boost_mode/score_mode, constant_score, trying to do a should match with multiple match_bool_prefix queries, etc. Nothing I've tried seems to achieve this.

Josh
  • 8,079
  • 3
  • 24
  • 49

1 Answers1

1

Try this:

{
  "query": {
    "bool": {
      "must": [
        {
          "multi_match": {
            "fields": [
              "display_name^50",
              "username^50"
            ],
            "query": "Jose",
            "type": "bool_prefix",
            "fuzziness": "AUTO",
            "tie_breaker": 0.3
          }
        }
      ]
    }
  }
}

Notice the effects of the tie_breaker being set to 0.0 as opposed to 0<x<1 and x=1.


Also note that your bool_prefix

scoring behaves like most_fields, but using a match_bool_prefix query instead of a match query.

Perhaps you indeed want the fields to be prefixed w/ jose. But if the username is, say, cool_jose, it's going to get left out (unless you for example apply an other-than-standard analyzer)...

Joe - GMapsBook.com
  • 15,787
  • 4
  • 23
  • 68
  • I think `tie_breaker` set to 0 works the way I was intending it to. At least in initial tests. I'll implement later and assuming it works, mark it as correct in a day or two. Thank you. For your second note, this is for a search-as-you-type deal. I do indeed want to use a prefix. I have a second endpoint for a more generic match and the frontend guys don't like the way it behaves for the use cases. – Josh Jul 09 '20 at 16:26
  • I hear ya. OK cool, let me know how the testing went. – Joe - GMapsBook.com Jul 09 '20 at 16:38
  • 1
    After implementing it in the application, it seems to do exactly what I was hoping for. Thanks for the assistance! – Josh Jul 11 '20 at 17:27
  • Glad to have helped! – Joe - GMapsBook.com Jul 11 '20 at 18:42