ES 分词器与中文分词
ES 分词器与中文分词
候选人小周在面试时被问到:"你们搜索'北京理工大学'能搜到吗?"
小周说:"能搜到啊。"
面试官追问:"那搜索'北京'呢?'理工'呢?'大学'呢?"
小周愣了一下:"应该都能搜到?"
面试官拿起电脑,说:"我给你跑个 demo 看看。"
结果发现:搜索"理工大学"能搜到,搜索"理工"一个字都搜不出来。
小周当场被问住了。
【面试官心理】 这道题我是在测试候选人对分词器的理解深度。很多候选人知道 ES 要分词,但不知道分词策略会直接影响召回率和精确率。这个"搜不出来"的坑,90% 用 ES 做中文搜索的团队都踩过。
一、分词器三大组件 🔴
1.1 组件拆解
ES 的分词器由三个组件串联而成:
1.2 常用分词器对比
1.3 自定义分词器示例
二、中文分词三大流派 🟡
2.1 词典匹配派 — IK
IK 是国内最流行的 ES 中文分词器,基于词典的前向最大匹配和后向最大匹配。
ik_max_word:穷举式切分,给出所有可能的组合。
ik_smart:智能切分,给出最合理的组合。
选 ik_smart 还是 ik_max_word?
ik_smart:精确搜索场景(如搜索框),用户输入短词,追求精确率ik_max_word:召回搜索场景(如搜索引擎),用户输入模糊,追求召回率
对于电商搜索,建议用 ik_smart 作为主分词器,再用 ik_max_word 建一个子字段用于高召回:
2.2 统计模型派 — HanLP / Jieba
HanLP 基于 CRF(条件随机场)和 HMM(隐马尔可夫模型),通过统计大量语料学习词边界。
优势:
- 能识别新词(未登录词),如"内卷"、"躺平"
- 支持词性标注、命名实体识别(NER)
- 英文和中文字符混合切分效果更好
劣势:
- 需要加载模型文件,部署复杂
- 首次加载慢,内存占用大
2.3 分词粒度对搜索的影响 🔴
这是面试中最高频的深水区。
召回率 vs 精确率:
最常见的翻车场景:
搜索"北京"能搜到"北京理工大学",但搜索"理工大学"一个字都搜不出来。因为 standard 分词器把中文按单字切了:
这个坑我在线上看过至少 10 次,团队排查了 3 天,最后发现就是 mapping 里忘了配中文分词器。
三、自定义分词器实战 🟡
3.1 停用词配置
中文停用词("的"、"了"、"和")在倒排索引中占据大量空间,但搜索价值极低。配置停用词可以:
- 减小索引体积:减少 15%~30% 的索引大小
- 提升查询性能:跳过无意义的词条
- 减少噪音结果:不会匹配到全是"的"的结果
3.2 同义词配置
同义词是搜索体验的关键环节。配置不当会导致:
- 用户搜"苹果手机"搜不到"iPhone"(差评来源 Top 1)
- 用户搜"电脑"搜不到"计算机"或"PC"
📖 点击展开:同义词的坑
同义词展开有两种策略:
1. 索引时展开(Index Time Synonym):
- 索引阶段就把"iPhone"和"苹果手机"存到同一个词条
- 查询时不需要额外处理
- 缺点:修改同义词后需要重建索引
2. 查询时展开(Search Time Synonym):
- 索引时原样存储
- 查询时动态展开同义词
- 缺点:每次查询都要做同义词转换
最佳实践:使用 Search Time Synonym,配置 synonyms_set,这样修改同义词后不需要重建索引。
四、错误示范
❌ 错误示范 1
候选人原话:"我把 description 字段设成了 keyword 类型,这样搜索就快了。"
问题诊断:
keyword字段不会分词,只能做精确匹配- 搜索"手机"搜不到"苹果手机"
- 完全混淆了"查询快"和"搜索有效"的区别
❌ 错误示范 2
候选人原话:"中文分词用 standard 就行,它会自动处理中文。"
问题诊断:
- standard 只识别空格和标点,中文按字切
- "北京理工大学"被切成 6 个单字
- 说明候选人没有实际测试过中文搜索效果
面试官内心 OS:"这两个候选人都是典型的'用过但没踩过坑'。他们可能觉得配置都对了,但从来没在线上验证过搜索结果的质量。直到用户投诉'搜什么都搜不到'才反应过来。"
五、生产避坑
5.1 分词器版本不一致翻车
线上后果:线下环境搜索正常,上线后搜索结果完全不对。
根因:线下和线上用了不同版本的 IK 分词器,词库差异导致分词结果不同。某些词在测试环境被正确切分,线上却被切成了另一个意思。
解决方案:
- 所有环境使用相同版本的分词器 jar 包
- 将自定义词典和同义词配置放到 config 目录的公共位置
- 上线前用固定的测试用例验证分词结果
5.2 自定义词典加载时机
线上后果:更新 IK 词典后,ES 重启前新词不生效,导致 3 天内的搜索都有遗漏。
根因:IK 的自定义词典在启动时加载,运行期间不会热更新。
解决方案:
或者使用动态同义词配置(synonyms 参数支持从文件加载,reload 时自动读取)。
六、工程选型
【面试官心理】 这道题我能看出候选人有没有被用户投诉"搜不到"折磨过。被投诉过的候选人,一定会去研究分词器的每一个参数,会去配同义词词典,会去测召回率。这种候选人,才是真正在 ES 上花了心思的。