【问题标题】:Trouble with has_parent query containing scripted function_score包含脚本 function_score 的 has_parent 查询出现问题
【发布时间】:2014-02-12 21:04:28
【问题描述】:

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

"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]: 查询失败[执行上下文重写失败]] ;嵌套:ElasticSearchIllegalArgumentException[No field found for [weight] in mapping with types [myChild]];

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

如果我不将score 用于score_type,则不会发生错误,尽管结果分数都是1.0,如记录所示。

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

【问题讨论】:

  • 赏金? :)
  • @DrTech 耐心,Iago,耐心;)
  • :D /me 耐心等待

标签: elasticsearch


【解决方案1】:

我会说这是一个错误:它使用myChild 映射作为默认上下文,即使您在has_parent 查询中。但我不确定修复这个错误有多容易。正确。

但是,您可以通过在完整的字段名称中包含 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

【讨论】:

  • 谢谢,成功了!我假设从脚本的子上下文中引用父级不会增加成本,因为它们总是在同一个分片中?
  • 正确 - 无需额外费用。
  • 奇怪的是 Martijn v Groningen 链接到来自 ES discussion topicgist 无法重现该问题。我很难看出有什么区别。无论如何,再次感谢。
  • 不同之处在于他没有在 URL 中指定类型,因此它在所有类型的映射中搜索一个名为 weight 的字段。因为我们在 URL 中指定了类型,所以它只搜索了myChild,而不是myParent
【解决方案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 cmets,那么您可以过滤所有帖子并根据 weight 对 cme​​ts 进行评分。我怀疑基于parents 评分childs 是可能的,尽管我可能错了:)

免责声明:堆栈溢出的第一个帖子...

【讨论】:

  • "您正在尝试根据parent 文档中的字段对child 文档进行评分" 您是说设计错误,还是解释错误?这个错误对我来说没有意义,因为script_scorehas_parent 查询中,所以我希望它可以在parent 文档上运行。
  • has_parent 查询返回具有特定父级的 child 文档。所以错误No field found for [weight] in mapping with types [myChild] 基本上是说script_score 函数试图访问weight 字段,该字段仅存在于myParent 中。所以是的,你需要改变设计。
  • 就像我说的,script_score has_parent,所以我希望doc 在脚本中引用myParent
  • 没有。 has_parent 将匹配 child 文档,因此您只有 child 文档,而不是 parents。您可能的意思是has_child 查询,它将匹配parent 文档与某个child。但同样,您会得到parent 文档和not child 文档,并且您无法根据parentschild 文档进行评分。想象一下 10 个childs 到一个parent:哪个孩子应该是最相关的?!
  • "has_parent 将匹配具有特定 parent" 的 child 文档 - 它会找到具有自己嵌套 query 的特定父级,查询父级。我正在尝试根据has_parentquery 中某些父母的分数对孩子们进行评分,这是基于我期望parent 上工作的脚本文件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-02-01
  • 2013-04-14
  • 1970-01-01
  • 2022-01-24
  • 1970-01-01
  • 2023-03-11
  • 2013-03-09
相关资源
最近更新 更多