Elasticsearch 将较短/不太相关的标题排在第一位

Can*_*yer 2 elasticsearch elasticsearch-ruby

我正在使用 Elasticsearch 7.3 进行产品搜索。产品标题的格式不一样,但我对此无能为力。

有些标题可能如下所示:

Ford Hub Bearing
Run Code Online (Sandbox Code Playgroud)

还有其他人这样的:

Hub bearing for a Chevrolet Z71 - model number 5528923-01
Run Code Online (Sandbox Code Playgroud)

如果有人搜索“雪佛兰轮毂轴承”,“福特轮毂轴承”产品排名第一,雪佛兰零件排名第二。如果我从产品标题中删除所有额外的文本(型号 5528923-01),雪佛兰部件将根据需要排名第一。

不幸的是,我无法修复产品标题,因此当有人搜索时,我需要能够将雪佛兰零件排名第一Chevrolet Hub Bearing。我只是将 的类型设置nametext并将standard分析器应用到我的索引中。这是我的查询代码:

{
    query:{

        bool: {
            must: [
                {
                    multi_match:{
                        fields: 
                            [
                               'name'
                             ],
                             query: "Chevrolet Hub Bearing"
                    }
                 }                  
            ]
        }

    }         
}
Run Code Online (Sandbox Code Playgroud)

Pie*_*let 6

Elasticsearch 在评分公式中使用 BM25 算法的字段长度。这就是为什么较长的文档即使匹配更多的术语也会排在第二位。

我建议您阅读有关 BM25 的精彩博客文章: how-shards-affect-relevance-scoring-in-elasticsearch 以及 -bm25-algorithm-and-its-variables

但您可以调整 bm25 算法来避免这种行为。这是elasticsearch 的bm25 文档,这里有一篇文章解释如何做到这一点

基于 TF/IDF 的相似性具有内置的 tf 标准化,并且应该更适合短字段(例如名称)。有关更多详细信息,请参阅 Okapi_BM25。这种相似性有以下选项:

k1 => 控制非线性项频率归一化(饱和度)。默认值为 1.2。

b => 控制文档长度标准化 tf 值的程度。默认值为 0.75。

discount_overlaps => 确定计算范数时是否忽略重叠标记(位置增量为 0 的标记)。默认情况下这是正确的,这意味着在计算范数时重叠标记不计算在内。

因此,您应该在索引设置中配置新的相似性,如下所示:

PUT <index>
{
  "settings": {
    "index": {
      "number_of_shards": 1
    },
    "similarity": {
      "my_bm25_without_length_normalization": {
        "type": "BM25",
        "b": 0
      }
    }
  },
  "mappings": {
    "doc": {
      "properties": {
        "name": {
          "type": "text",
          "similarity": "my_bm25_without_length_normalization"
        }
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

然后,如果将停止对较长的名字进行评分。其他字段将保留长度标准化。