ES 0.90 的 completion suggester 之所以敲一两个字母就立刻返回提示,核心原因是它不在查询的时候实时遍历匹配,而是在写入索引阶段就提前把所有候选提示词构建成 FST 有限状态转换器,并且把 FST 持久化保存到索引段文件里,用户输入前缀的时候,只是沿着 FST 图做字符路径游走,不需要扫描大量文档,所以速度极快,毫秒级就能出结果。底层依赖 Lucene 的 AnalyzingSuggester,FST 本身是一张压缩的字符图,相同前缀的词会共用前面的路径,只在不同字符位置分叉,非常适合前缀自动补全场景,普通 prefix 查询是查询时扫词条,而它把高成本的构建工作全部前置到索引阶段。
一、核心底层结构:FST 有限状态转换器
- FST 本质是一张有向字符图,把所有候选提示词压缩存储,共享公共前缀
- 每个节点代表一个字符,一条完整路径就对应一条候选提示词,还附带权重、附加数据
- 构建 FST 计算开销很大,排序、合并、压缩都耗 CPU,所以设计上放在索引期一次性做完
- FST 会跟着 Lucene 段一起写入磁盘,ES 打开索引时加载进内存,后续查询直接复用
二、索引期(提前预计算)完整步骤
- 定义 mapping,单独声明一个 type 为 completion 的专用字段,这个字段不能用普通字符串字段
- 写入文档时,给 completion 字段传入 input 候选词列表、weight 权重、output 展示文本、payload 附加数据
- 使用索引分析器对 input 做分词、归一化处理,得到标准化后的候选字符串
- 把所有标准化后的候选词,按权重排序,交给 Lucene AnalyzingSuggester 生成 FST
- FST 序列化,写入当前 Lucene 段的索引文件,和倒排索引放在一起保存
- 段合并的时候,多个段的 FST 会重新合并、生成新的 FST,旧段文件被清理
三、查询期(用户敲字母时做的事情)
- 用户输入前缀,先用 search_analyzer 做同样的文本归一化
- 在已经加载好的 FST 图里,从起点顺着输入字符一步步走路径
- 如果前缀路径存在,遍历这个节点后面所有分支路径,收集候选词
- 按照预先存好的 weight 权重排序,返回指定数量的提示结果
- 整个过程没有扫描倒排、没有遍历文档,只是图上遍历,所以敲 2 个字母也秒出提示
四、和普通 prefix 前缀查询的区别
| 方式 | 计算时机 | 查询开销 | 适用场景 |
|---|---|---|---|
| completion suggester | 索引期构建 FST | 极低,图遍历 | 输入时自动补全、联想提示 |
| prefix query | 查询时扫描词条 | 高,遍历倒排 | 少量前缀检索,不适合打字实时提示 |
五、这个方案自带的短板
- 字段必须单独定义 completion 类型,不能直接拿普通 text 字段当提示
- 删除文档不会立刻从 FST 里移除,要等段合并重建 FST 才会生效
- FST 占用堆内存,候选词越多,内存占用越高
- 只支持前缀匹配,不支持中间、后缀模糊匹配
- ES0.90 版本里这个功能还是实验性特性,后续版本有改动
【相关 FAQ】
问题 1:ES0.90 的 completion suggester 的 FST 是每次查询都重新构建吗?
回答 1:不是,ES0.90 的 completion suggester 的 FST 是索引写入阶段提前构建并持久化到索引段,查询阶段只会读取、遍历 FST,不会重新构建,只有段合并的时候才会重建 FST。
问题 2:ES0.90 的 completion suggester 能不能直接用普通 string 字段做自动提示?
回答 2:不能,ES0.90 的 completion suggester 要求必须单独配置 completion 类型字段,普通 string 字段不会在索引阶段生成 FST,无法使用这套预计算的提示逻辑。
问题 3:ES0.90 的 completion suggester 敲两个字母就返回提示,是预存了所有 2 字母前缀列表吗?
回答 3:不是预存全部前缀列表,而是预构建 FST 图,FST 天然支持任意长度前缀游走,不管输入 1 个、2 个还是多个字母,都是沿着字符路径查找,不需要提前枚举所有前缀。
【参考资料】
[2026-10-26](刚敲两个字母就有提示,ES 0.90 的 completion suggester 是怎么提前算好的)腾讯云开发者社区
[2013-08-22](You Complete Me)Elastic 官方博客
【免责声明】
本内容仅为技术原理科普,ES0.90 属于比较老旧的版本,该版本 completion suggester 存在实验性限制,不建议直接在生产环境照搬;不同版本 Elasticsearch 底层实现存在差异,实操前请核对对应版本官方文档,本内容不承担任何线上故障、业务损失相关责任。
