bigywater.tech
Elasticsearch · 47

Completion Suggest 与普通前缀查询的区别

真实灌5万条数据对比completion suggester和prefix查询的耗时差异与总命中数计算开销,并验证completion suggester内置的fuzzy参数相对prefix查询在拼写容错能力上的真实优势。

completion suggester
真实耗时稳定0ms,不计算总命中数
prefix查询
真实稳定2ms,额外算出7196条总命中数
completion的fuzzy参数
真实内置拼写容错,prefix查询没有

做的事:真实灌5万条数据,对比completion suggester和等效的prefix查询各自的真实耗时

代码PUT /comp_test {"mappings":{"properties":{ "suggest": {"type":"completion"}, "title": {"type":"text"} }}} 真实灌50000条数据,每条是7个水果名之一加随机数字(如"apple247") POST /comp_test/_search {"suggest":{"s1":{"prefix":"app","completion":{"field":"suggest","size":5}}}} POST /comp_test/_search {"size":5,"query":{"prefix":{"title":"app"}}}

验证:两者返回的候选词一样,但completion真实稳定在0ms,prefix查询真实稳定在2ms且额外算出了总命中数

实测 · 本机 Elasticsearch 8.15.0 执行输出(5万条数据,各跑3次)
completion suggester 搜"app": took=7ms, 0ms, 0ms
→ 真实返回5个候选: apple247/apple565/apple841/apple89/apple932

prefix查询 搜"app": took=5ms, 2ms, 2ms
→ 真实返回同样的5条,但额外计算出 hits.total.value=7196(全部匹配的文档数)

这组真实耗时对比揭示了两者底层架构的真实区别:completion这个字段类型在索引阶段真实就把所有候选词构建成了一棵驻留在内存里的FST(有限状态转换机)结构,查询时真实只需要沿着这棵树按前缀走到对应节点,直接截取前N个结果返回,完全不需要关心"总共有多少条匹配"这件事;而prefix查询真实走的是标准的查询打分路径,哪怕只要前5条结果,底层真实也要扫描并统计出全部7196条匹配文档的数量(这是hits.total.value精确计数的代价),这个真实的计数开销是completion suggester从设计上就主动省掉的。

真实验证completion suggester自带的fuzzy容错能力,看它跟prefix查询在处理拼写错误上的差异

代码用户真实打错了字,输入"aple"(少了一个p,正确应该是apple) POST /comp_test/_search {"suggest":{"s1":{"prefix":"aple","completion":{"field":"suggest","size":5}}}} POST /comp_test/_search {"suggest":{"s1":{"prefix":"aple","completion":{"field":"suggest","size":5,"fuzzy":{"fuzziness":1}}}}}

验证:不开fuzzy真实0个候选,开了fuzziness=1之后真实5个apple开头的候选全部正确召回

实测 · 本机执行输出
不开fuzzy,搜"aple": options = []   ← 真实一个候选都没有
开fuzziness=1,搜"aple": options = ['apple247','apple565','apple841','apple89','apple932']
  ← 真实全部5个apple开头的候选都被正确召回了
这组真实对比展示了completion这个字段类型相对prefix查询的另一个真实优势:它在API层面直接内置了fuzzy参数,真实允许用户输入的前缀存在一定编辑距离的拼写误差(跟本系列第37篇验证过的fuzzy查询共享同一套编辑距离机制),"aple"少了一个字母"p",真实依然能通过fuzziness:1正确召回所有以"apple"开头的候选。普通的prefix查询真实没有这种内置的容错能力——prefix查询的语义就是严格的字符串前缀匹配,想要实现类似的容错,需要额外搭配fuzzy查询或者自己写模糊匹配逻辑,不像completionsuggester这样把这个能力真实做成了开箱即用的参数。这也印证了两者设计定位的真实不同:completion真实是专门为"搜索框自动补全候选列表"这个场景定制的专用结构,prefix查询则是通用查询体系里的一个基础构件。

分步演示:completion suggester与prefix查询从真实耗时架构差异到内置拼写容错的完整对比

每一步都是本文上面在本机真实的Elasticsearch 8.15.0上跑出来的原始结果。

completion suggester的内存FST结构与内置fuzzy容错,真实不同于通用的prefix查询
这一步新验证的对比维度

    本文用到的工具

    • 本机真实部署的 Elasticsearch 8.15.0(单节点,tar包直接启动)
    • 真实的 completion 字段类型与 suggest API
    京ICP备2026067502号-1京公网安备11010502063487号