包含脚本化function_score的has_parent查询出现问题

时间:2014-01-22 16:57:29

标签: elasticsearch

我有两种文件类型,处于父子关系中:

"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](过滤后的(功能得分(ConstantScore()),function = script [_score * doc ['weight'] .value],params [null])) - > cache(_type:myParent))) - > cache(_type:myChild)],来自[0],size [10]:查询失败[无法执行上下文重写]];嵌套:ElasticSearchIllegalArgumentException [在使用类型[myChild]进行映射时找不到[weight]的字段];

似乎不是将评分函数应用于父级,然后将其结果传递给子级,ES试图将评分函数本身应用于子级,从而导致错误。

如果我不对score使用score_type,则不会发生错误,但结果分数全部为1.0,如文档所述。

我在这里缺少什么?如何根据父字段使用自定义评分查询这些子文档?

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:2)

我认为问题在于您尝试根据child文档中的字段对parent个文档进行评分,而功能评分应该反过来。

要解决这个问题,我的想法是将父/子关系和得分与子文档存储在一起。然后,您将过滤子文档并根据子文档中的weight对其进行评分。

一个例子:

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

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

现在,您可以使用has_parent过滤器选择具有特定child的所有parent个文档,然后使用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过滤所有帖子并对评论进行评分。我怀疑基于childs得分parents是可能的,尽管我可能错了:)

免责声明:堆叠溢出的第一篇帖子......