Matthew Rideout
Matthew Rideout

Reputation: 8546

Elasticsearch Boost Specific Result Only For Specific Query

I have a database of 250,000 foods from the usda, copied into Elasticsearch. People search for foods by name. For certain queries like "flour", there is a specific flour that I want to always show up first. There are about 100 common items I want to do this for. Most items are fine with the normal search results.

However, for other queries, like "almond flour", there is a different result I'd like to always show up first. (there are many varieties of each type of flour, and I need some control on which is best for a given generic query).

Is there an ability to boost a result only if the search query matches a regular expression? For example, my elasticsearch document for the food item could also include the regular expression that must match the search query, in order for the boost to take place. Example es doc:

{
  "name": "Pork, cured, salt pork, raw",
  "boostRegex": "/^pork$/i"
}

Otherwise, is there an ability to boost a result only if the search query exactly matches a keyword in the document? I attempted this method, but I couldn't seem to make boostKeyword exact matching work. For example, if one item was boostKeyword: "almond flour" and another was boostKeyword: "coconut flour", and the search query was "flour" - both would get boosted if the boost keyword matched. Example:

{
    "name": "Flours, almond, blanched",
    "boostKeyword": "almond flour"
},
{
    "name": "Flours, coconut, fine",
    "boostKeyword": "coconut flour"
},

Example query I used with this problem

"query": {
    "bool": {
        "must": {
            "match": {
                "name": searchQuery
            }
        },
        "should" : [
            {
              "match" : {
                  "boostKeyword" : {
                      "query" : searchQuery,
                      "boost": 10
                  }
              }
            }
        ]
    }
}

Upvotes: 0

Views: 1298

Answers (1)

Matthew Rideout
Matthew Rideout

Reputation: 8546

I ended up accomplishing this by creating a secondary database I perform a lookup from, before querying elasticsearch. I would prefer to just store this data inside of the elasticsearch item's document, and use it at query-time with some sort of script to perform the boost. But this will do.

The secondary database (it's actually a firebase firestore collection) holds regular expressions for items I want to boost, with the ID number of the item that should be boosted during the elasticsearch query.

Before my elasticsearch query, I query this database and return all of the regular expressions. For each expression that matches my search term, I add to an array of "should / or" statements for the elasticsearch query.

The should statement boosts any search result that contains the matched ID numbers.

"body": {
    "query": {
        "bool": {
            "must": {
                "match": {
                    "name": searchQuery,
                }
            },
            "should" : [
                boostArray
            ]
        }
    }
}

Boost Array: I generate an array of objects like this, which are simply included in the "should" array in the elasticsearch query (See above). This works for if I have multiple items that should be boosted for a given query.

let boostArray = {
    "match" : {
        "sourceId" : {
            "query" : "14091",
            "boost": 1
        }
    }
},
{
    "match" : {
        "sourceId" : {
            "query" : "14016",
            "boost": 1
        }
    }
}

Upvotes: 1

Related Questions