Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elastic Search using NEST Field Boosting

I am using Elastic Search in C# using the NEST strongly typed client. I have an index containing Entries:

[ElasticType(Name = "Entry", IdProperty = "Id")]
public class Entry
{
    public string Id { get; set; }
    public string Title { get; set; }
    public string Description { get; set; }
    public string Award { get; set; }
    public int Year { get; set; }
}

Where Year is the year of the entry, eg 2012, and Award is the type of Award the Entry won, which can be null.

I then want to search these Entries using boosting for different properties. In the following code, I want results to be ranked higher that match on the Title, than those that match on the Description.

private IQueryResponse<Entry> GetMatchedEntries(string searchText)
{
    return _elasticClient.Search<Entry>(
                body =>
                body.Query(q => 
                           q.QueryString(qs => 
                                         qs.OnFieldsWithBoost(d => 
                                                              d.Add(entry => entry.Title, 5.0)
                                                              .Add(entry => entry.Description, 2.0))
                           .Query(searchText))));
}

I have now been asked to Boost the results by those which have won Awards, and also Boost newer Entries (ie by the Year).

How do I do this? Is it something that needs to be done as part of the indexing service, or as part of the search?

like image 277
tmortiboy Avatar asked Jan 16 '13 12:01

tmortiboy


People also ask

What is boosting in Elasticsearch?

Returns documents matching a positive query while reducing the relevance score of documents that also match a negative query. You can use the boosting query to demote certain documents without excluding them from the search results.

What is NEST Elasticsearch?

NEST is an official high-level client created by Elasticsearch that maps all requests and responses as types and provides an interface to execute queries. Let's add the NEST Client from NuGet via package manager or by running the following command from the directory where the .csproj file lives: dotnet add package NEST.

What is Elasticsearch relevance score?

The score represents how relevant a given document is for a specific query. The default scoring algorithm used by Elasticsearch is BM25.


1 Answers

You can achieve this through a combination of a boosting query and custom_score query

instead of boosting year we alter the score based on the year because:

(_score + 2013) > (_score + 1999)

Newer results will float to the top.

By using a boosting query we can effectively demote results that are missing the award field.

see: https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-boosting-query.html https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html

_client.Search<Entry>(s=>s
    .Query(q =>q
        .Boosting(bq=>bq
            .Positive(pq=>pq
                .CustomScore(cbf=>cbf
                    .Query(cbfq=>cbfq
                        .QueryString(qs => qs
                            .OnFieldsWithBoost(d =>
                                d.Add(entry => entry.Title, 5.0)
                                .Add(entry => entry.Description, 2.0)
                            )
                            .Query(searchText)
                        )
                    )
                    .Script("_score + doc['year'].value")
                )
            )
            .Negative(nq=>nq
                .Filtered(nfq=>nfq
                    .Query(qq=>qq.MatchAll())
                    .Filter(f=>f.Missing(p=>p.Award))
                )
            )
            .NegativeBoost(0.2)
        )
    )
);
like image 149
Martijn Laarman Avatar answered Oct 06 '22 03:10

Martijn Laarman