0
votes

I have a multi-match query which is matching against five different fields. I want to limit how much of an impact this multi-match query has on the overall query so that if for some reason, one of the fields has just been spammed with the search term(s), it doesn't get a massive score. What I want is a decaying impact. I have trawled through the documentation and I'm struggling to find a way to do this. I have found the decay script functions docs (https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/function-score-query-usage.html) but they all seem to be specific to a single field which doesn't really help me as I want to apply it to a multi match query.

Here is the query I want to limit the impact of:

new MultiMatchQuery
{
    Type = TextQueryType.MostFields,
    Fields = Field<SearchableTour>(f => f.Name, 0.5)
        .And(Field<SearchableTour>(f => f.StartCity, 0.1))
        .And(Field<SearchableTour>(f => f.FinishCity, 0.1))
        .And(Field<SearchableTour>(f => f.Description, 0.05))
        .And(Field<SearchableTour>(f => f.ItineraryText, 0.01)),
    Query = searchText,
    Operator = Operator.And
}

The underlying data is not controlled by me and someone could theoretically just fill one of these fields with common search terms to artificially boost their result to the top. I want to prevent this but still allow these fields to have a limited impact. There doesn't seem to be any concept of a "max score" which would allow me to restrict the combined score for these fields.

1

1 Answers

0
votes

I think you're on the right path. You should be able to just plug your MultiMatchQuery into the query part of the link you provided, and then provide whatever score functions you want. Note however that the decay functions provided are for numeric, date or geo_location fields, so you probably can't use those. What I would probably do is something like this:

new FunctionScoreQuery()
{
    Query = new MultiMatchQuery{ ... },
    ScoreMode = FunctionScoreMode.Sum,
    Functions = new List<IScoreFunction>
    {
        new ScriptScoreFunction { Script = new InlineScript(##YourDecayFunction(_score)##) }
    }
}