Problem with has_parent request containing scripted function_score

I have two types of document in parent-child relation:

"myParent" : { "properties" : { "weight" : { "type" : "double" } } } "myChild" : { "_parent" : { "type" : "myParent" }, "_routing" : { "required" : true } } 

The weight field should be used for custom counting / sorting. This request directly against parent documents works as intended:

 { "query" : { "function_score" : { "script_score" : { "script" : "_score * doc['weight'].value" } } } } 

However, when I try to do a similar count for child documents with a has_parent request has_parent I get an error:

 { "query" : { "has_parent" : { "query" : { "function_score" : { "script_score" : { "script" : "_score * doc['weight'].value" } } }, "parent_type" : "myParent", "score_type" : "score" } } } 

Error:

QueryPhaseExecutionException [[myIndex] [3]: query [filtered (ParentQuery [myParent] (filtered (function rating (ConstantScore (:), function = script [_ score * doc ['weight']. Value], params [null]) ) → cache (_type: myParent))) → cache (_type: myChild)], from [0], size [10]: Query Failed [context correspondence failed]]; inested: ElasticSearchIllegalArgumentException [Field not found for [weight] when matching with types [myChild]];

It seems that instead of applying the count function to the parent element and then passing its result to the child element, ES tries to apply the count function to itself, causing an error.

If I do not use score for score_type , an error does not occur, although the score is then 1.0 , as described.

What am I missing here? How can I request these child documents with a custom count based on the parent field?

+2
source share
2 answers

I would say that this is a mistake: myChild mapping is used as the default myChild , even if you are inside the has_parent request. But I'm not sure how easy it is to fix the error. properly.

However, you can get around it by specifying the type name in the name of the full field:

 curl -XGET "http://localhost:9200/t/myChild/_search" -d' { "query": { "has_parent": { "query": { "function_score": { "script_score": { "script": "_score * doc[\"myParent.weight\"].value" } } }, "parent_type": "myParent", "score_type": "score" } } }' 

I opened the problem to find out if we can get this fixed # 4914

+6
source

I think the problem is that you are trying to clog child documents based on the field in the parent document and that the evaluation of the function should be the other way around.

To solve this problem, my idea was to keep the parent / child relationship and account with child documents. You will then filter the child documents and evaluate them according to the weight in the child document.

Example:

 "myParent" : { "properties" : { "name" : { "type" : "string" } } } "myChild" : { "_parent" : { "type" : "myParent" }, "_routing" : { "required" : true }, "properties": { "weight" : { "type" : "double" } } } 

Now you can use the has_parent filter to select all child documents that have a specific parent , and then enroll them using the function score :

 { "query": { "filtered": { "query": { "function_score" : { "script_score" : { "script" : "_score * doc['weight'].value" } } }, "filter": { "has_parent": { "parent_type": "myParent", "query": { "term": { "name": "something" } } } } } } } 

So, if the parent documents were blog posts and child comments, then you can filter all posts and rate comments based on weight . I doubt that childs -based scoring of parents is possible, although I might be wrong :)

Disclaimer: first post for ...

+2
source

All Articles