平均子查询的分数,不包括不适用的分数

时间:2016-08-01 07:49:46

标签: elasticsearch

我正在尝试在索引上构建自定义分数。分数基于几个标准,比如说(不介意这是否真的相关,这只是一个例子):

  1. 项目的“尺寸”是否低于3英寸(加权系数:2)
  2. 项目的“离家”的距离是否低于3英里(加权因子:3)
  3. 该项目的“评级”是3星级还是更多,......(加权因子1)
  4. 我的得分是这样的:对于这三个匹配的标准中的每一个,得分为1.然后,平均这些(即除以所有加权因子的总和),但还有一个额外的伎俩:一个标准不能匹配(即“大小”对于一个项目为空,或者“离家”的距离),那么,我必须排除这个未知的加权因子。

    示例:如果item_1匹配所有三个标准,则得分为:

    Criterion 1 : 1 (score) * 2 (weight)
    Criterion 2 : 1 (score) * 3 (weight)
    Criterion 3 : 1 (score) * 1 (weight)
    Sum of weight for available criteria : 6
    Total : 6/6 = 1 (fairly simple)
    

    如果item_2符合条件1和2但没有评级,我们会排除标准3的权重,得分如下:

    Criterion 1 : 1 (score) * 2 (weight)
    Criterion 2 : 1 (score) * 3 (weight)
    Criterion 3 : not available => 0
    Sum of weight for available criteria : 5, as we exclude 3
    Total : 5/5 = 1
    

    问题是:我能有效地做到吗?

    到目前为止我所拥有的:

    • 为每个crietrion编写查询很简单:{"term" : { "size" < 3 }}
    • 将它们组合在一起作为加权因子的总和很容易,我做了一个功能分数的bool查询

    这可以这样:每个函数都是基于过滤器的,得分为1,我们使用boost模式“replace”来替换任何查询结果,并使用“should”来添加个人匹配。

    我们将此查询称为sumQuery

    "{ "bool" : {
        "should" : [
          { "function_score" : {
            "functions" : [
              { 
                "filter": { "term" : { "size" < 3 }},
              }
            ],
            "score_mode": "sum",
            "boost_mode": "replace",
            "boost": 2
          }
          // Other criteria
        ]
      }
    }
    

    现在,为了计算如何划分这个总和,我只能想到的是构建一个脚本函数,比如说:

    sumOfWeights=6d;
    if (doc['size'].value == null) sumOfWeights -= 2;
    if (doc['ratings'].value == null) sumOfWeights -= 1;
    // ...
    return _score/sumOfWeights;
    

    使用此函数编写mainQuery

    "query": {
      "function_score": {
        "query": **mainQuery**,
        "functions" : [ {
          "script_score" : {
            "script" : **script above**
          }
        } ]
      }
    }
    

    这对我来说似乎过于复杂,并且在我的索引上会变得很慢(尤其是脚本部分)并且给出了标准的数量。你有什么(更好的)想法吗?

1 个答案:

答案 0 :(得分:0)

requested evolution应该可以缓解这种情况。

涉及:

  1. 能够在function_score的函数中添加查询,从而允许任意组合查询分数
  2. 能够按名称引用每个子function的分数
  3. 如果过滤器不匹配,则设置“不匹配”值(例如,值0)的能力,从而在{avg的某些情况下使weight组合更好1}}不会被考虑在内
  4. 选项2几乎提供了问题所需的所有内容,因为一旦您可以访问每个项目的个人分数,您就可以决定将哪一个考虑在内。

    选项1允许以不同方式处理事物,例如通过提出计算标准总和的子请求,以及另一个计算权重来除以它。