Elasticsearch数组评分

时间:2014-08-11 13:20:51

标签: elasticsearch scoring

我使用elasticsearch搜索我的类型中的多个数组字段,类似于

t1 =  { field1: ["foo", "bar"],
        field2: ["foo", "foo", "foo", "foo"]
        field3: ["foo", "foo", "foo", "foo", "foo", "foo"]
}

然后我使用multi_match查询来获取匹配项,

multi_match: { query: "foo",
                fields: "fields*"
              }

当计算t1的分数时,elasticsearch在field1,field2和field3中添加查询的分数,这是我想要的。然而,他们并没有做出同样的贡献,因此,field3对得分的贡献最大,而且#34; foo"在那里发生多次。

我现在想通过不添加所有数组条目的分数来计算每个数组字段中的分数,而只是计算它们的最大值。在我的示例中,包含的所有字段都具有相同的分数,因为它们都具有完全匹配。

这个问题已在elasticsearch forum上提出,但到目前为止尚未得到解答。

1 个答案:

答案 0 :(得分:0)

我自己也对此感到难过,看起来应该有一种简单的内置方式来指定max而不是sum。

不确定这是否与您的目标一致,因为您丢失了阵列中任何特定项目的匹配分数。因此,您没有获得最佳特定项目的匹配分数的最大值,如果有任何匹配则只是一个布尔值。如果它是一个更细微的东西(比如一个人的全名,你希望在第一个和最后一个比一个或另一个更好的匹配),这可能是不可接受的,因为你扔掉了你的分数。

如果可以接受,此解决方法似乎有效:

{function_score: {
  query: {bool: {should: [
    {term: {field1: 'foo'}},
    {term: {field2: 'foo'}},
    {term: {field3: 'foo'}},
  ]}},  
  functions: [
    {filter: {term: {field1: 'foo'}}, weight: 1},
    {filter: {term: {field2: 'foo'}}, weight: 1},
    {filter: {term: {field2: 'foo'}}, weight: 1},
  ],
  score_mode: 'sum',
  boost_mode: 'replace',
}}

我们需要“查询”部分给我们进一步过滤的结果,即使我们丢弃了分数。这似乎应该是一个过滤器,但只是在filtered查询中包装同样的东西是行不通的。这里可能有更好的选择。

然后,如果该字段匹配,则weight函数基本上给出1,否则为0。 score_mode告诉它将这些权重相加,所以在你的情况下它们都匹配所以我们得到3. boost_mode告诉如何与原始查询结合,“replace”告诉它忽略原始查询得分(你提到的问题是数组中的多个匹配正在相加)。因此,此查询的总分为3,因为有3个匹配。

对我来说似乎更复杂,但在我相对有限的测试中,我没有注意到性能问题或任何事情。如果有更熟悉elasticsearch的人有一个更好的答案,我很乐意看到更好的答案。