Skip to content

ElasticSearch 全文检索:倒排索引 + IK 分词 + BM25

示例代码:examples/es-test/

为什么有了 Milvus 还要 ES

ES 和 Milvus 解决的是两类根本不同的问题

Milvus(语义检索)ES(词条检索)
匹配逻辑「意思差不多」「字面差不多」
适合输入自然语言问句、模糊概念术语、编号、代码、人名、地名
典型成功搜「杭州旅游」命中「西湖攻略」errorCode=5001 只命中 5001
典型失败i7-13700K 可能漂到 i7-12700K搜「西湖攻略」搜不到「杭州旅游」

ES 管理论关键词匹配,Milvus 管语义相似度——组合起来才是混合检索。

倒排索引 vs 正向索引

MySQL(正向索引):文档 → 关键词。搜「跑步」需要遍历每一行匹配 content 字段,O(n)。

ES(倒排索引):关键词 → 文档列表。

"今天" → [1, 2, 3]
"跑步" → [1, 2]
"骑车" → [3]

搜「跑步」→ 直接定位 [1, 2],O(1) 找词 + BM25 排序

IK 中文分词器

ES 默认 standard 分词器按空格切——对英文好用,对中文是灾难:

分词器「混合检索知识库」
standard ...(逐字拆)
ik_max_word混合 检索 知识 知识库 (穷举)
ik_smart混合 检索 知识库(语义单元)
  • ik_max_word:尽可能多切——召回率高
  • ik_smart:最少切分——精准度高

项目实践:索引时用 ik_max_word(词条全),查询时用 ik_smart(精准匹配)。

BM25 打分

BM25 是 ES 默认的相关性打分算法,核心看两件事:

  1. 词频(TF):查询词在文档里出现多少次?有上限,不会无限涨
  2. 逆文档频率(IDF):这个词在整个语料库有多「稀有」?越稀有贡献越大

搜「LangGraph Agent」→「Agent」在很多文档都有(IDF 低),「LangGraph」较稀有(IDF 高),包含「LangGraph」的文档排前面。

BM25 不关心语义,只关心「词出现没、多不多、稀不稀有」。

混合检索 + Rerank:完整流水线

纯关键词 + 纯语义到达瓶颈后,下一步是:

           ┌─→ ES BM25 关键词检索 ─→ hits_es ─┐
用户问题 ──┤                                   ├─→ 合并去重 ─→ Rerank 精排 ─→ LLM
           └─→ Milvus Embedding 语义检索 ─→ hits_milvus ─┘

Rerank 是精排质检员——粗召保证「不漏」,精排保证「不噪」。用更强的模型(如 qwen3-rerank)对每条文档和原问题做精确相关性打分,取 top 3 送 LLM。

Embedding 模型Rerank 模型
输入一段文本一个问题 + 一条文档
输出向量相关性分数
做什么粗筛精排
速度快(向量索引)慢(逐对计算)

核心收获

  • 倒排索引 = 搜索引擎的「书末索引」——先有它再有 BM25
  • IK 分词器 = ES 中文检索的入口——没有它,ES 搜中文基本废了
  • 混合检索 = 两条腿走路——ES 关键词兜底专有名词,Milvus 语义兜底自然语言
  • Rerank 是最后一关——把 20 条粗召结果精筛到 3 条,Token 省了、噪声降了