Dynamic scoring based on doc field


(Vitalii) #1

Hi I am using elasticsearch 6.4 and I was trying to find any workable solution for my problem. So my problem is I have doc and I am trying to score depending on id from query:

{ "rates": [ { "id": 1, "score_rate": 4.0}, { "id": 2, "score_rate": 5.0}, { "id": 3, "score_rate": 0.0} ] }

  • The rates field is nested. What I was trying to achieve is based on the query boost score. initially I used script_function:
    {"script_score": {"script": {"params": {"id": 1, "min": 0.0}, "id": "secondary_rate"}}

Where secondary_rate is script in painless

double min_threshold = (double) params.min;
double score = min_threshold;

for (int i = 0; i < params._source.rates.length; ++i){
     def rate = params._source.rates[i];
     if (rate.id == params.id){
        c_score = category.score_rate;
        break;
}
}
return c_score;

But this doesn't work because nested field can't accessed in script throughout doc['rates'] and _source field is not available anymore (Painless null pointer exception) in script_functions.

  • In second attempt I tried to use combination of NestedQuery and FieldValueFactor
    something that look like: Nested value on function score. But unfortunately NestedQuery make second query and join (I can't control how joined is performed) results of it with root query, and if root query is empty Result of NestedQuery just added to root results. This behavior is unacceptable for my business logic.

  • On third attempt I tried to reindex rates field as array and encoded info about id in to array index so field from example above will look like:
    { "rates": [0, 4.0, 5.0, 0.0]}
    Again I used script function, but there is no guarantee for order of elements. To have elements in the
    same order as in index time I need to use _source field (that is not available in 6.4).

So I am kind of stuck on this problem and have no ideas how to solve it. So any suggestions or hints are very welcome. Thank you in advance


(Vitalii) #2

Probably no one will reply. So in case you have the same problem I opened discussion on StackOverflow: