← 返回题目列表

Elasticsearch 的相关性评分是怎么计算的?BM25 怎么理解?

高频 困难 第 20 / 30 题 更新于 2026/07/28
ElasticsearchBM25相关性评分_score

简化版

Elasticsearch 默认会给匹配文档计算 _score,用来表示文档和查询的相关程度。现代 Elasticsearch 默认相似度算法是 BM25,可以粗略理解为:查询词在文档中出现越多越相关,越稀有的词权重越高,字段越短命中越集中,但词频增长不是无限线性加分。

详细版

相关性评分的目标是把“更像用户想要的结果”排在前面。BM25 主要考虑三类因素:

  1. TF:词在当前文档中出现的频率。出现次数多,通常更相关。
  2. IDF:词在整个索引中有多稀有。越少见的词,区分能力越强。
  3. 字段长度归一化:短字段命中关键词通常比长字段偶然命中更有意义。

例如搜索“Java 并发”:

  • 标题是“Java 并发面试题”的文章,通常分数高。
  • 正文几万字里只出现一次“并发”的文章,分数可能低。
  • “的”“是”这类高频词区分度低,权重不应该高。

实际业务中还可以通过:

  • 字段 boost:标题权重大于正文;
  • function_score:结合热度、时间、新鲜度;
  • minimum_should_match:控制至少匹配多少词;
  • explain API:查看评分原因;
  • 调整 analyzer:提升分词质量。

但面试要强调:评分不是数据库排序那么简单,它依赖倒排索引统计信息、字段配置和查询写法。

完整版教学

一、为什么搜索需要评分

精确查询只需要判断“等不等”,全文检索需要判断“更相关还是不相关”。

例如用户搜索:

Elasticsearch 分片 原理

下面两篇文章都命中关键词:

A:Elasticsearch 分片原理与集群设计
B:常见搜索系统介绍,正文某处提到 Elasticsearch,也提到分片

如果只返回匹配结果,不排序,用户体验会很差。相关性评分就是为了解决排序问题。

二、TF:词出现越多,通常越相关

TF 可以理解为 term frequency。一个查询词在文档里出现多次,说明文档可能更围绕这个主题。

但 BM25 不会让词频无限线性加分。因为一个词出现 100 次并不一定比出现 10 次相关 10 倍,它可能只是堆关键词。BM25 对词频增长做了饱和处理,避免纯堆词把评分冲得过高。

这也是搜索评分和简单计数不同的地方:它既承认词频有价值,也限制词频的过度影响。

三、IDF:越稀有的词越有区分度

IDF 可以理解为 inverse document frequency。一个词如果几乎每篇文档都有,它对区分文档帮助很小;如果只有少量文档包含,它的区分度就很强。

例如在技术文章里:

  • “Java”可能很多文档都有;
  • “AQS”出现得更少;
  • “StampedLock”可能更少。

用户搜“Java StampedLock”时,StampedLock 对排序的影响通常应该比 Java 更明显。

四、字段长度归一化:短字段命中更集中

同样命中“分片原理”,标题只有 10 个词且完整命中,通常比一篇很长正文里偶然出现一次更相关。

这就是字段长度归一化的直觉:

短标题:Elasticsearch 分片原理
长正文:几万字文章里某段提到分片原理

命中密度不同,相关性也不同。

五、业务上如何调相关性

实际搜索通常不只依赖默认评分,还会结合业务权重。

多字段权重:

{
  "query": {
    "multi_match": {
      "query": "Java 并发",
      "fields": ["title^3", "summary^2", "content"]
    }
  }
}

标题权重 ^3 表示标题命中更重要。

结合业务热度:

{
  "query": {
    "function_score": {
      "query": {
        "match": { "title": "Elasticsearch" }
      },
      "field_value_factor": {
        "field": "view_count",
        "modifier": "log1p",
        "factor": 0.2
      }
    }
  }
}

这样可以让“文本相关性”与“业务热度”一起影响排序。但要控制权重,避免热门但不相关的内容压过真正相关的内容。

六、如何排查评分不符合预期

排查相关性问题可以按这个顺序:

  1. _analyze 看查询词和文档字段如何分词。
  2. explain 查看某篇文档的评分细节。
  3. 检查字段类型是否正确,全文字段是否误用了 keyword
  4. 检查查询写法,精确条件是否放进了 filter。
  5. 检查字段 boost、同义词、停用词、minimum_should_match 是否合理。
  6. 如果排序还要结合时间、热度、销量,再考虑 function_score 或单独排序策略。

七、常见误区与追问

因素直觉解释面试表达
TF文档里出现次数多次出现更相关,但 BM25 会饱和
IDF词在全库稀有程度越少见越有区分度
字段长度命中密度短字段命中通常更集中
boost/function_score业务调权文本相关性之外叠加标题、热度、时间等信号
文档 A 标题 8 个词,命中 “BM25” 1 次
文档 B 正文 8000 个词,命中 “BM25” 1 次
在其他条件接近时,A 往往更像用户想找的结果。

记忆钩子:BM25 不是“数词频”,而是“词频有用、稀有词更贵、短字段命中更集中”。

一个数字例子:Java 出现在 10 万篇文档里的 6 万篇,StampedLock 只出现在 800 篇。用户搜 Java StampedLock 时,后者的 IDF 更高,对排序区分更强;如果某篇文章把 StampedLock 堆了 100 次,BM25 的词频饱和也会抑制它无限加分。

  • 误区:_score 越高就绝对越好。 _score 只在同一次查询、相同索引和相近查询条件下有比较意义,不适合作为跨查询的绝对分数。
  • 误区:BM25 只看词出现次数。 它还考虑 IDF、字段长度归一化,并对词频增长做饱和处理。
  • 误区:业务排序只能靠 _score 生产里常用字段 boost、function_score、时间衰减、热度、销量等信号共同排序。
  • 追问:为什么罕见词权重大? 罕见词能更有效区分文档,几乎每篇都有的词对判断相关性帮助很小。
  • 追问:评分异常先看什么? 先用 _analyze 看分词,再用 explain 看评分细节,随后检查 mapping、boost、同义词和 query 写法。
  • 追问:为什么不能盲目加大热门度权重? 热门度过强会让不够相关但点击高的内容压过真正相关内容,搜索体验会偏离用户查询意图。

八、加强记忆

记住“BM25 看三件事:词多不多、词稀不稀、字段长不长”。面试时先解释 _score 的意义,再讲 TF、IDF、字段长度归一化,最后补充业务调权和排查工具,这题就很完整。