I am looking for ways to solve the problem of changing the score of documents corresponding to the query:
I need to change the primary score by increasing it by the value of the “booster field of the document that corresponds to the query. To request a document search, I use NativeQuery.builder:
Query filmQuery = NativeQuery.builder()
.withQuery(...)
...
.build();
To change the estimate, there is an option to apply in NativeQuery “.withRescorerQuery()”, to which to pass the RescorerQuery rescorerQuery,
consisting including of Query rescoreQuery:
private final ***Query query***;
private ScoreMode scoreMode = ScoreMode.Default;
@Nullable private Integer windowSize;
@Nullable private Float queryWeight;
@Nullable private Float rescoreQueryWeight;
- It is not clear which query is needed in this Query rescoreQuery to change score.
I assumed that it is possible to apply “withScriptedField”, to which an object of the ScriptedField type should be passed.
In turn, scriptedField consists of String fieldName and ScriptData scriptData. - It is not clear which field name is required to be specified in fieldName.
I specified the name “booster”, already intuitively, because it is not clear which of the fields of the required document needs to be specified (if we are talking about the document field at all).
The situation with ScriptData is even more interesting: when opening the ScriptData class, the IDEA development environment issues a warning “Library source does not match the bytecode for class Script Data”.
I don’t know how the JVM will compile the code,
but I have compiled the Script Data object in this form:
ScriptData scriptData = new ScriptData(ScriptType.INLINE , "painless" , "score += doc['booster'].value" , "newScore-script" , Collections.emptyMap());
- If something is wrong in scriptData, I will be glad to comment.
As a result, all this is in the code below:
ScriptData scriptData = new ScriptData(ScriptType.INLINE
, "painless"
, "score += doc['booster'].value"
, "newScore-script"
, Collections.emptyMap());
Query scriptQuery = NativeQuery.builder()
.withScriptedField(new ScriptedField("booster", scriptData))
.build();
RescorerQuery rescorerQuery = new RescorerQuery(scriptQuery);
Query filmQuery = NativeQuery.builder()
.withQuery(q -> q.bool(b -> {...}))
.withRescorerQuery(rescorerQuery)
.withSort(sortParam.get())
.withPageable(Pageable.ofSize(pageSize))
.build();
//Next, this request is passed as part of the List QueryList in this code:
List<SearchHits<?>> searchHits = operations.multiSearch(queryList, classes, indexCoordinatesList);
An error is issued regarding this code with “searchHits”:
2023-10-14T11:43:13.972+05:00 ERROR 13640 — [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: co.elastic.clients.util.MissingRequiredPropertyException: Missing required property ‘RescoreQuery.query’] with root cause
with what is stated above:
RescorerQuery rescorerQuery = new RescorerQuery(scriptQuery);
I would be grateful for help in solving the problem.
P.S.
Initially, such a request was sent to the index, which gave the expected result:
{ "from": 0, "size": 100, "query": {
"function_score": {
"query":{
"bool":{
"must": {
"match": {
"title": {
"query": "Fan"
}
}
},
"filter":[
{"match":{"age":18}},
{"bool":{
"filter":[
{ "terms":
{ "genres.uuidGenre": ["c6bee588-3b47-4307-ba00-40764d50a57a", "fe6b5d15-bf73-4b34-a02e-13d110c89a3f"] } },
{ "terms": { "countries.uuidCountry": ["24cb3786-d85c-418c-af90-c719c2a5a796" , "ee88f16d-8492-42d8-8dff-3cd0f10d7121"] } }
]
}
}
]
}
},
"field_value_factor": {
"field": "booster",
"modifier": "log2p"
}
} } }
As a result, I found a solution using “FunctionScoreQueryBuilder”, but I can’t figure out how to implement it, not to mention how to pass this function either to a query or to “operations.multiSearch”
to change the primary score by increasing it by the value of the “booster field of the document that corresponds to the query
If you want to adjust the original score instead of replacing it, you should use function_score
instead of query rescore. I don’t have a spring data setup, but here is an example you can run in Kibana console to see what I mean:
PUT test/_bulk?refresh
{"index": {}}
{"foo": "bar", "val": 10 }
{"index": {}}
{"foo": "bar", "val": 2 }
{"index": {}}
{"foo": "bar", "val": 0 }
{"index": {}}
{"foo": "bar" }
{"index": {}}
{"foo": "baz", "val": 10000 }
GET test/_search
{
"query": {
"function_score": {
"boost_mode": "sum",
"query": {
"match": {
"foo": "bar"
}
},
"field_value_factor": {
"field": "val",
"missing": 0
}
}
}
}