首页 文章

Elasticsearch数组评分

提问于
浏览
3

我正在使用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中添加查询得分,这就是我想要的 . 但是,他们并没有做出同样的贡献,因为“foo”在那里出现多次,所以field3对得分的贡献最大 .

我现在想要计算每个数组字段中的分数,不是将所有数组条目的分数相加,而是仅计算它们的最大值 . 在我的示例中,包含的所有字段将具有相同的分数,因为它们都具有一个完全匹配 .

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

1 回答

  • 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',
    }}
    

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

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

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

相关问题