0
votes

Sorry for the confusing title.

I'm trying to build a query that searches either the game title or a unique id, but only return one result if a unique id is searched (and found).

For example, here is a search using the term "Portal 2". Portal 2 won't match any of the "ids.name" fields so it does a search in the "name" key and returns that game properly.

{
   "index":"games",
   "type":"game",
   "body":{
      "query":{
         "bool":{
            "should":[
               {
                  "nested":{
                     "path":"ids",
                     "query":{
                        "term":{
                           "ids.name":{
                              "value":"Portal 2",
                              "boost":2
                           }
                        }
                     }
                  }
               },
               {
                  "match":{
                     "name":{
                        "query":"Portal 2"
                     }
                  }
               }
            ]
         }
      }
   }
}

And here is the same thing with the search term "portal-2-45218" which does an exact match on ids.name. It matches the first "should" query properly but also returns games found from the second query.

{
   "index":"games",
   "type":"game",
   "body":{
      "query":{
         "bool":{
            "should":[
               {
                  "nested":{
                     "path":"ids",
                     "query":{
                        "term":{
                           "ids.name":{
                              "value":"portal-2-45218",
                              "boost":2
                           }
                        }
                     }
                  }
               },
               {
                  "match":{
                     "name":{
                        "query":"portal-2-45218"
                     }
                  }
               }
            ]
         }
      }
   }
}

How would i go about somehow stopping the search once an exact match from "ids.name" is found?

1

1 Answers

0
votes

There's no real way to "stop the search" which is also something I don't think you want to do. You're handling two kinds of query intents here (free text and exact id match) and eagerly searching both cases just in case the exact id match has no results.

There are two ways you could approach this: 1) Heavily boost one of the "should" clauses to ensure the results are typically first 2) Execute each kind of search separately using a multisearch (concurrent searches) and check app side whether the more optimal search has results. If not, fall back to the second.

For Option 1, you currently have a boost of 2, and could bump that up to 20 or something. It's kinda hacky, but given that results will ONLY surface on exact ID matches, you're safe to jack up the boost (experiment in production for the right value)

Option 2, leverage the msearch endpoint. In this case, if the first query returns results you only gotta return those!

/_msearch
{"index" : "games", "type" : "game"}
{
  "query":{
    "nested":{
      "path":"ids",
      "query": { "term":{ "ids.name":{ "value":"portal-2-45218" } } }
    }
  }
}
{"index" : "games", "type" : "game"}
{
  "query":{
    "match": { "name": { "query":"portal-2-45218" } }
  }
}