2014-01-22 113 views
2

我有两个文档类型,在一个父子关系:麻烦与has_parent查询function_score

"myParent" : { 
    "properties" : { 
    "weight" : { 
     "type" : "double" 
    } 
    } 
} 

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

weight字段是要被用于定制的得分/排序。该查询直接对母文件按预期工作:

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

然而,试图用一个has_parent查询子文档做类似的进球时,我得到一个错误:

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

的错误是:

QueryPhaseExecutionException[[myIndex][3]: query[filtered(ParentQuery[myParent](filtered(function score (ConstantScore(:),function=script[_score * doc['weight'].value], params [null]))->cache(_type:myParent)))->cache(_type:myChild)],from[0],size[10]: Query Failed [failed to execute context rewrite]]; nested: ElasticSearchIllegalArgumentException[No field found for [weight] in mapping with types [myChild]];

好像而不是应用打分函数给家长,那么它的结果传递给孩子,ES尝试应用评分向孩子发生作用,导致错误。

如果我没有使用score作为score_type,则不会发生错误,虽然结果得分然后全部为1.0,如记录。

我在这里错过了什么?我如何通过基于父字段的自定义评分来查询这些子文档?

+0

赏金? :) – DrTech

+0

@DrTech耐心,伊阿古,耐心;) –

+0

:D /我耐心地等待 – DrTech

回答

6

此我想说的是一个错误:它使用的是myChild映射,默认情况下,即使您在has_parent查询。但我不确定这个bug是多么容易修复。正常。

然而,你可以解决它通过包括type名在满场的名字:

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" 
    } 
    } 
}' 

我开了一个问题,看看我们是否能得到这个固定#4914

+0

谢谢,这就是诀窍!我认为从脚本的子上下文中引用父代不会增加成本,因为它们将始终处于同一个分片中? –

+0

正确 - 无额外费用。 – DrTech

+0

奇怪的是,Martijn v格罗宁根从[ES讨论主题](https://groups.google.com/forum/#)链接到[gist](https://gist.github.com/martijnvg/8639841) !msg/elasticsearch/w7zgncPYMVY/K3qRlpd7TQ0J)无法重现问题。我很难看出有什么不同。无论如何,再次感谢。 –

2

我认为问题在于您试图根据parent文档中的字段对child文档进行评分,并且功能评分应该是相反的。

为了解决这个问题,我的想法是将父/子关系和分数存储在子文档中。然后,您将筛选子文档并根据子文档中的weight对它们打分。

一个例子:

"myParent" : { 
    "properties" : { 
     "name" : { 
      "type" : "string" 
     } 
    } 
} 

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

现在你可以使用has_parent过滤器来选择具有一定parent,然后将所有child文件使用function score得分他们:

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

所以如果parent文件是博客文章和child评论,那么你可以过滤所有帖子,并根据weight评分评论。我怀疑,基于parents得分childs可能,虽然我可能是错的:)

免责声明:1后溢出堆栈...

+0

“你正在试图根据'parent'文件中的一个字段对'child'文件进行评分你是说设计错了,或解释错误?这个错误对我来说没有意义,因为'script_score'在'has_parent'查询中,所以我希望它能在'parent'文件上运行。 –

+0

'has_parent'查询返回具有某个父级的'child'文档。因此,在映射类型[myChild]时发现错误'没有为[weight]找到字段“,这基本上是说'script_score'函数试图访问'weight'字段,该字段仅存在于'myParent'中。所以是的,你需要改变设计。 – truemped

+0

就像我说过的,'script_score'是* has_parent'中的*,所以我期望'doc'在脚本中引用'myParent'。 –