When I am trying to make a query_string request to my Elasticsearch that uses a function_score (script_score
) to manipulate its default score. But I always seem to get a base _score
of 1.0
.
My model looks like this:
{
"name": "Secret Birthday Party",
"description": "SECRET! Discuss with discretion",
"_userCounters": [
{
"user": "king",
"count": 12
},
{
"user": "joseph",
"count": 1
}
]
}
My request with the function_score script looks like this:
{
"query" : {
"function_score" : {
"query": {
"query_string": {
"query": "secret",
"analyze_wildcard": true,
"fields": [
"name", "description"
]
}
},
"script_score": {
"script": {
"inline" : "int scoreBoost = 1; for (int i = 0; i < params['_source']['_userCounters'].length; i++) { if (params['_source']['_userCounters'][i].user == 'joseph') { scoreBoost += params['_source']['_userCounters'][i].count; } } return scoreBoost;"
}
}
}
}
}
What I am getting is a result which finds exactly what I want, but only returns the value from the function_score script. The built-in scoring does not seem to work anymore. This is the response I am getting:
{
"_index": "test3",
"_type": "projects",
"_id": "7",
"_score": 2, // this is exactly the return value of the script_score. What I want instead is that this value gets multiplied with the normal score of ES
"_source": {
"name": "Secret Birthday Party",
"description": "SECRET! Discuss with discretion",
"_userCounters": [
{
"user": "queen",
"count": 12
},
{
"user": "daniel",
"count": 1
}
]
}
}
My guess is that my request body is not in the correct format since all scores are just 1.0
when I take the function_score out completely.
I figured it out. It was actually a problem with the script itself and not with the structure of the request body.
The function was only returning the factor which is supposed to be multiplied with the _score
value. Instead it needs to do the multiplication itself.
Here is the script a bit more readibale:
int scoreBoost = 1;
for (int i = 0; i < params['_source']['_userData'].length; i++) {
if (params['_source']['_userData'][i].user == '{userId}') {
scoreBoost += params['_source']['_userData'][i].count;
}
}
// the error was here: only the scoreBoost value was returned
// the fix is to multiply it with the _score value
return _score * scoreBoost;