Elasticsearch Scoring function is based on maximum value in array / nested
I have a field inside my document that stores an array of integers.
Java class:
public class Clazz {
public List<Foo> foo;
public static Foo {
public Integer bar;
public Integer baz;
}
}
Mapping:
"properties" : {
"foo" : {
"properties" : {
"bar" : {
"type" : "integer"
},
"baz" : {
"type" : "integer"
}
}
}
}
Examples of documents:
{
id: 1
foo: [
{ bar: 10 },
{ bar: 20 }
]
},
{
id: 2
foo: [
{ bar: 15 }
]
}
Now I would like to make my account. Counting function gives the value of input
: 10
.
And the scoring function basically has: "The closer foo.bar
to input
, the higher the score. And if foo.bar
lower than input
, the score will only be half good
Request:
"function_score" : {
"functions" : [ {
"script_score" : {
"script" : "if(doc['foo.bar'].value >= input) { (input - doc['foo.bar'].value) * 1 } else { (doc['foo.bar'].value - input) * 2 }",
"lang" : "groovy",
"params" : {
"input" : 10
}
}
} ],
"score_mode" : "max",
"boost_mode" : "replace"
}
Expected Result:
id 1
must be first because there is foo.bar
one that matches input=10
.
What's happening:
Scoring works great if documents have only one value foo.bar
. If an array (like in doc c id 1
) Elasticsearch seems to take the last value in the array.
What the request should do:
Take your best score. This is why I used score_mode: max
. But it seems that this only respects the array functions
in function_score
and not (as I expected) the possible evaluations inside the function.
I read somewhere about usage doc['foo.bar'].values
( s value instead of value), but I don't know how to use it in this case.
Do you have an idea how to do this?
source to share
One way to achieve this with groovy is as follows: you can use the maximum list method by values.
Example:
{
"query": {
"function_score": {
"functions": [
{
"script_score": {
"script": "max_score=doc[\"foo.bar\"].values.max();if(max_score >= input) {return (max_score - input);} else { return (max_score - input) *2;}",
"lang": "groovy",
"params": {
"input": 10
}
}
}
],
"score_mode": "max",
"boost_mode": "replace"
}
}
}
source to share