第三阶段 29 · suggester 自动补全(搜索框联想 / 拼写纠错)

29 · suggester 自动补全(搜索框联想 / 拼写纠错)

阶段:第二三阶段补充 / 查询结果处理

ES:completion / term / phrase suggester | PostgreSQL:pg_trgm 相似度 / 前缀索引


1. 概念

三种建议器,解决不同问题:

suggester 作用 场景
completion 前缀实时补全(基于 FST,极快) 搜索框输入即联想
term 逐词纠错(编辑距离) "拼错了帮我改对"
phrase 整句纠错(term 的升级,考虑上下文) "did you mean ..."

completion 需要字段类型是 completion,写入时把候选词喂进去。


2. PostgreSQL 对照

sql 复制代码
-- 前缀补全:前缀索引 + LIKE
SELECT name FROM products WHERE name LIKE 'think%' ORDER BY name LIMIT 10;

-- 拼写纠错:pg_trgm 相似度
SELECT name FROM products ORDER BY name <-> 'thnkpad' LIMIT 5;

ES 的 completionLIKE 'x%' 快得多(内存 FST);term/phrase 类似 pg_trgm 纠错。


3. ES DSL

3.1 completion:mapping + 写入 + 补全

复制代码
PUT products_idx
{ "mappings": { "properties": {
    "name":        { "type": "text" },
    "name_suggest":{ "type": "completion" }
} } }

POST products_idx/_doc
{ "name": "ThinkPad X1", "name_suggest": ["ThinkPad X1", "X1 Carbon"] }

POST products_idx/_search
{
  "suggest": {
    "s": {
      "prefix": "think",
      "completion": { "field": "name_suggest", "size": 5 }
    }
  }
}

3.2 term / phrase:纠错

复制代码
POST products_idx/_search
{
  "suggest": {
    "correct": {
      "text": "thnkpad",
      "term": { "field": "name" }
    }
  }
}

4. Spring Boot 实现

java 复制代码
@Component
public class Doc29Suggester {

    @Autowired
    private ElasticsearchClient elasticsearchClient;

    /** 前缀补全,返回候选词列表 */
    public List<String> complete(String indexName, String prefix) throws IOException {
        SearchResponse<Void> resp = elasticsearchClient.search(s -> s
                .index(indexName)
                .suggest(sg -> sg.suggesters("s", su -> su
                        .prefix(prefix)
                        .completion(c -> c.field("name_suggest").size(5)))),
                Void.class);

        return resp.suggest().get("s").stream()
                .flatMap(entry -> entry.completion().options().stream())
                .map(opt -> opt.text())
                .collect(Collectors.toList());
    }
}

completion suggester 的结果在 resp.suggest()Map<String, List<Suggestion>>),

entry.completion().options() 里的 text()。搜索建议不占 hitssize(0) 亦可。


5. 坑与最佳实践

  1. completion 是独立字段 :要单独 mapping + 写入候选词,不是给已有 text 直接加的。
  2. completion 占内存:FST 常驻堆内存,候选量极大时评估内存。
  3. 要拼音/中文补全:需装分析插件(如 pinyin / IK),默认分词对中文补全不友好。
  4. 纠错用 phrase 更稳term 逐词纠,phrase 结合上下文更准,适合"你是不是要找"。
  5. 补全 vs 搜索是两件事 :补全给候选词,用户选定后再发一次正常 search

下一篇

进入第三阶段聚合能力:20-metric-指标聚合.md


← 上一篇:28-collapse-字段折叠去重总览下一篇:30-index-document-写入 →

相关推荐
倒流时光三十年20 小时前
第三阶段 24 · filter / filters 桶聚合
es
倒流时光三十年1 天前
第二阶段 17 · multi_match 多字段匹配
es
倒流时光三十年1 天前
第三阶段 23 · 嵌套与子聚合 / top_hits
es
倒流时光三十年1 天前
第二阶段 19 · _source 字段裁剪
es
倒流时光三十年3 天前
第二阶段 15 · prefix / wildcard / fuzzy 模糊匹配
es
粗体鱼3 天前
RAG/Agent 记忆混合检索多路召回:RRF 算法与Chunk RRF、Document RRF如何决策TopK
postgresql·milvus·es·rag·rff·mermory
huisheng_qaq2 个月前
【项目篇-01】Vmware虚拟机和环境安装配置
redis·mysql·canal·rocketmq·es·vaware虚拟机
JAVA面经实录9172 个月前
Elasticsearch 完整版完整知识体系
java·elasticsearch·搜索引擎·es
代码讲故事2 个月前
在没有kibana的ES(elasticsearch)线上生产环境集群中,如何通过命令行修改或增加字段而不需要reindex?
大数据·elasticsearch·搜索引擎·命令行·es·索引·模版