Techlead
Techlead

Reputation: 182

Boosting elasticsearch results with NEST when a secondary field is a specific value

I have a large index of Ice Cream objects.

public class IceCream
{
    public string Description {get; set;}
    public bool IsGeneric { get; set; }
    public double Price { get; set; }
}

I have a large database of products that are used to make ice cream milkshakes. The business mostly uses a generic white label product but can at times be forced to use a branded product due to supply chain issues. Please see the example data below for reference.

Here is a simplified example of a C# Nest based query.

        var searchInputText = "Ben & Jerries double choc";

        var query = new MatchQuery()
        {
            IsVerbatim = false,
            Field = "description",
            Query = searchInputText
        };

        var search = new SearchRequest()
        {
            Query = query,
            From = 0,
            Size = 30
        };

        var results = client.Search<IceCream>(search);

The query works perfectly when searching for branded products. However, searching for "Double Choc" returns Ben & Jerries Double Choc with a higher relevance than the generic "Double Choc" product.

Is there a way via Nest to utilise "should" to boost the IsGeneric = true field to ensure that when no brand is included in the search the generic listing has the highest relevance?

i.e. Searching for "Double Choc" one would expect...

  1. Double Choc
  2. Ben & Jerries Double Choc
  3. etc.

Searching for "Ben & Jerries Double Choc" one would expect...

  1. Ben & Jerries Double Choc
  2. Dan's Double Choc
  3. etc.

Note: This is a heavily simplified example. The real world application contains 100,000 manufacturing component variances so the relevance issue is far more dramatic than it appears here.

Upvotes: 0

Views: 1087

Answers (1)

Aaron M. Eshbach
Aaron M. Eshbach

Reputation: 6510

Yes, you can use a Boosting query.

client.Search<IceCream>(s => 
    s.Query(q => 
        q.Boosting(b => 
            b.Negative(n => n.Term("isGeneric", false))
             .Positive(p => p.Match(m => m.Field("description").Query(searchInputText)))
             .NegativeBoost(0.2))));

By Boosting IsGeneric = false with a Negative Boost of 0.2, you can demote all results without IsGeneric = true by a constant value.

Upvotes: 1

Related Questions