ElasticSearch 全文检索入门:倒排索引 + IK 分词器 + BM25 相关性算法
前言
业务搜索场景下,MySQL 的 like '%关键词%' 只适合极小体量数据,无法分词、无法相关性排序、性能低下。 Elasticsearch (简称 ES) 是目前主流开源全文搜索引擎,底层基于 Lucene。 全文检索三大核心基石:倒排索引(存储结构) + IK 分词器(中文文本切割) + BM25(相关性打分排序)。 本文从原理 → REST‑API 详解 → 实操完整案例,带你从零入门中文全文检索。
一、三大核心原理
1. 倒排索引:搜索引擎的底层基石
正向索引(传统数据库存储)
文档 ID → 文档原文内容
doc1: 春天来了,春暖花开
doc2: 春天适合踏青
查询关键词时,需要逐条扫描全部文档,数据量大查询速度极慢。
倒排索引(ES 存储结构)
词条 (Term) → 对应文档 ID 列表
春天: [doc1,doc2]
来了: [doc1]
春暖花开: [doc1]
适合: [doc2]
踏青: [doc2]
优势:搜索关键词直接根据词条定位文档,不需要全库扫描,查询速度极快。 构建倒排索引的前置条件:文本分词;中文必须借助中文分词器切割词条。
2. IK 分词器:中文搜索必备插件
ES 自带standard标准分词器,中文会被拆成单个汉字,完全无法用于词语搜索。 示例原文:春暖花开 standard 分词结果:春、暖、花、开
IK‑Analyzer 国内最流行的开源中文分词插件,提供两种分词模式:
- ik_max_word(索引写入阶段推荐):最细粒度拆分,穷尽所有可匹配词语
春暖花开 → 春天、春暖、春暖花开、花开
- ik_smart(查询搜索阶段推荐):粗粒度最少切分,无冗余词条
春暖花开 → 春暖花开
最佳实践:写入索引用 ik_max_word;查询搜索用 ik_smart IK 支持自定义扩展词典,可以添加行业新词、网络热词、专业术语。
3. BM25 相关性打分算法(ES8.x 默认评分算法)
BM25(Best‑Matching‑25)是 ES 默认相关性排序算法,用来替代老旧的 TF‑IDF,解决词频越高得分无限上涨、长文档打分不公平问题。

参数说明
- (f(q_i,D)):词条在当前文档出现次数 (词频 TF)
- IDF:逆文档频率;稀有词汇权重更高
- (|D|):当前文档长度
- avgdl:索引内所有文档平均长度
- (k_1=1.2):词频饱和系数,词频达到一定程度分数不再暴涨
- (b=0.75):文档长度惩罚系数,过长文档自动降权
BM25 核心特性:词频收益有上限,文档堆砌关键词不会拿到超高分数,搜索结果更加公平。 TF‑IDF VS BM25:TF‑IDF 词频越高得分无上限;BM25 做了饱和截断,现代搜索优先使用 BM25。
二、ES REST‑API 接口全面讲解
ES 所有操作都是基于 HTTP RESTful API,默认端口 9200,请求方式:GET/POST/PUT/DELETE。
1. 分词调试接口 /_analyze
接口地址:
POST http://127.0.0.1:9200/_analyze作用:分词预览调试工具。不会创建索引,不会保存任何数据。用来测试一段文本会被分词器切成哪些词条。
开发必用!排查分词错误的第一手段。分词结果错误,生成的倒排索引就错误,后续搜索必然搜不到内容。
① 全局测试分词,不绑定索引
POST 127.0.0.1:9200/_analyze
{
"analyzer": "ik_smart",
"text": "春暖花开去踏青"
}
analyzer:指定分词器,ik_smart/ik_max_word/standardtext:待切割原文
返回结果重点查看tokens数组,就是切割完成的词条。
② 复用索引字段已经配置好的分词器测试
POST 127.0.0.1:9200/article/_analyze
{
"field": "title",
"text": "春暖花开去踏青"
}
article:索引名称;field:复用 mapping 里面 title 字段配置好的分词器。
2. 创建索引 PUT /索引名
接口地址:
PUT /article作用:新建索引,等价于 MySQL 新建数据库 + 建表。索引 = 数据库 / 数据表;文档 = 数据表的一行数据。
完整版,配置分片、映射、分词器:
PUT /article
{
"settings": {
"number_of_shards": 1,
"number_of_replicas": 0
},
"mappings": {
"properties": {
"title":{
"type":"text",
"analyzer":"ik_max_word",
"search_analyzer":"ik_smart"
},
"content":{
"type":"text",
"analyzer":"ik_max_word",
"search_analyzer":"ik_smart"
}
}
}
}
analyzer:写入文档构建倒排索引时,使用 ik_max_word 细粒度分词search_analyzer:用户搜索查询时,使用 ik_smart 粗粒度分词
⚠️注意:PUT 仅支持新建索引;索引一旦创建成功,不能直接修改 mapping,需要重建索引。
3. 查询索引配置 GET /索引名
GET /article查看索引 settings、mappings 全部配置;排查字段分词器配置是否生效。
4. 删除索引 DELETE /索引名
DELETE /article删除整个索引,文档数据、倒排索引全部清空,谨慎操作。
5. 新增单条文档 POST /索引名/_doc/[id]
POST /article/_doc/1
{
"title":"春天踏青攻略",
"content":"春暖花开,周末适合出门踏青游玩"
}
_doc:ES7 + 版本固定文档类型关键字/1:自定义文档唯一 ID;省略 ID 时 ES 自动生成随机 ID
写入成功后 ES 自动执行:文本分词 → 生成词条 → 构建倒排索引。
6. 批量导入文档 POST /索引名/_bulk
POST /article/_bulk
{"index":{"_id":1}}
{"title":"春天踏青攻略","content":"春暖花开,周末适合出门踏青游玩"}
{"index":{"_id":2}}
{"title":"夏季避暑指南","content":"炎炎夏日,寻找清凉避暑胜地"}
{"index":{"_id":3}}
{"title":"春日旅游推荐","content":"春暖花开,各地迎来春游高峰期"}
高性能批量导入接口,大批量数据导入首选 bulk,效率远高于单条循环插入。
7. 根据 ID 精确查询文档 GET /article/_doc/1
GET /article/_doc/1
根据文档 id 查询原始文档内容;不属于全文检索,不走 BM25 打分,不分词搜索。
8. 更新文档 POST /索引名/_update/1
POST /article/_update/1
{
"doc":{
"title":"新版踏青攻略"
}
}
ES 文档更新底层逻辑:删除旧文档、新建文档,重新分词,重建倒排索引。
9. 删除单条文档 DELETE /article/_doc/1
DELETE /article/_doc/1
10. 全文检索搜索接口 GET /索引名/_search
ES 最核心搜索接口
GET /article/_search
{
"query":{
"match":{
"content":"春暖花开踏青"
}
},
"highlight": {
"fields": {
"content":{}
}
}
}
全文检索执行流程:
- 用户输入搜索关键词
- 使用字段配置的
search_analyzer分词 - 查询倒排索引筛选候选文档
- BM25 算法自动计算相关性得分
_score - 按照_score 分数降序返回结果
match查询:分词后全文检索,走 BM25 打分;term查询:精确匹配、不分词,适合标签、状态、id 字段。
11. 集群运维查看接口
#查看集群健康状态
GET /_cat/health?v
#列出所有索引
GET /_cat/indices?v
ES 通用 API 端点对照表
表格
| 端点 | 功能说明 |
|---|---|
_analyze |
分词调试工具 |
_doc |
文档单条 CRUD |
_bulk |
高性能批量操作 |
_search |
全文检索查询 |
_update |
文档局部更新 |
_cat |
集群、索引状态查询 |
三、完整实操步骤(ES 8.X)
⚠️前置要求:IK 分词器版本号必须和 Elasticsearch 版本完全一致
步骤 1:安装 IK 分词插件
离线安装(推荐)
- 下载与 ES 版本一致的 IK‑Analyzer zip 包
- 在 ES
plugins目录新建ik文件夹,解压所有文件放入 - 重启 Elasticsearch 服务
在线安装示例命令
bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v8.15.0/elasticsearch-analysis-ik-8.15.0.zip
步骤 2:验证 IK 分词是否生效
调用_analyze接口,返回正常中文词语分词结果代表安装成功。
步骤 3:创建索引,配置 IK 分词器(参考上面 PUT /article 示例)
步骤 4:导入测试文档数据(bulk 批量插入)
步骤 5:执行全文检索查询,获取 BM25 打分搜索结果
完整开发调用顺序:
- PUT 创建索引 + 配置 mappings 分词器
- POST _analyze 调试分词效果(必做!)
- POST _bulk 导入文档,生成倒排索引
- GET _search 执行全文检索
可选:自定义 BM25 打分参数
PUT /article
{
"settings": {
"similarity": {
"my_bm25": {
"type": "BM25",
"k1": 1.5,
"b": 0.6
}
}
},
"mappings": {
"properties": {
"content":{
"type":"text",
"analyzer":"ik_max_word",
"search_analyzer":"ik_smart",
"similarity":"my_bm25"
}
}
}
}
四、全文检索完整工作链路
- 写入文档:原始文本 → IK 分词器 (ik_max_word) 切割词条 → 构建倒排索引存储
- 用户搜索:搜索关键词 → IK 分词器 (ik_smart) 切割查询词条
- 检索匹配:词条命中倒排索引筛选候选文档集合
- 相关性排序:BM25 算法打分,按照相关性从高到低返回搜索结果
五、高频踩坑清单
- ❌坑 1:未安装 IK 分词器,中文只能单字分词,搜索不到结果
- ❌坑 2:创建索引忘记指定 IK 分词器;mapping 配置错误,必须重建索引才能生效
- ❌坑 3:IK 分词器版本与 ES 版本不一致,ES 启动失败
- ❌坑 4:索引写入阶段使用 ik_smart 分词;词条丢失,召回率下降,搜不到相关文档
- ✅最佳搭配方案:索引
ik_max_word+ 查询ik_smart+ 默认 BM25 打分
六、进阶拓展方向
- IK 自定义词典:
IKAnalyzer.cfg.xml配置 ext_dict 扩展词库,添加行业新词 - 混合检索:BM25 关键词召回 + 向量检索语义召回,RAG 知识库系统标配
- 自定义打分:
function_score在 BM25 分数基础上叠加热度、时间权重

浙公网安备 33010602011771号