【问题标题】:Elasticsearch array scoringElasticsearch 数组评分
【发布时间】:2014-10-04 08:11:12
【问题描述】:

我正在使用 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 forum 上提出过,但目前还没有回答。

【问题讨论】:

  • 怎么样,创建一个只有唯一关键字的字段,然后在该字段中搜索?
  • 对我来说并不是一个真正的选择,因为实际上,每个 foo 都是一个包含 foo 的完整句子。

标签: elasticsearch scoring


【解决方案1】:

我自己也被这个问题难住了,似乎应该有一种简单的内置方法来指定最大值而不是总和。

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

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

{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 boost_mode告诉如何与原始查询结合,“替换”告诉它忽略原始查询分数(它有您提到的问题是数组中的多个匹配项被求和)。所以,这个查询的总分是 3,因为有 3 个匹配项。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-24
    • 2019-02-10
    • 2015-08-27
    • 1970-01-01
    相关资源
    最近更新 更多