Elasticsearch数组评分



我使用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对得分的贡献最大,因为"foo"在那里出现了多次。

我现在想通过不加所有数组条目的分数来计算每个数组字段内的分数,而只是取其中的最大值。在我的例子中,所有包含的字段都有相同的分数,因为它们都有一个精确匹配。

这个问题已经在elasticsearch论坛上问过了,但是到目前为止还没有回答。

我自己也被这个问题难住了,似乎应该有一个简单的内置方法来指定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的人有一个更好的答案,我很想看到一个更好的答案。

最新更新