elasticSearch之API:建议器(suggest)
文章目录
- 一、建议器简介
- 1、简介
- 2、四大建议器对比
- 二、四种建议器介绍与使用
- 1. Completion Suggestor(自动补全建议器)
- (1)工作原理
- (2)适用场景
- (3)关键参数
- (4)使用示例(DSL)
- (5)使用实战
- 2. Term Suggestor(单词拼写纠错建议器)
- (1)工作原理
- (2)适用场景
- (3)关键参数
- (4)使用示例(DSL)
- (5)使用实战
- 3. Phrase Suggestor(短语拼写纠错建议器)
- (1)工作原理
- (2)适用场景
- (3)关键参数
- (4)使用示例(DSL)
- (5)使用实战
- 4. Context Suggestor(上下文感知自动补全建议器)
- (1)工作原理
- (2)适用场景
- (3)关键参数
- (4)使用示例(DSL)
- (5)使用实战
- 三、Java高级客户端使用建议器
- 1. 依赖配置(Maven)
- 2. 客户端初始化
- 3.实战场景:商品搜索建议
一、建议器简介
1、简介
官方文档:https://elasticsearch.bookhub.tech/rest_apis/search_apis/suggesters
ES建议器本质是通过“预计算”或“实时相似度匹配”,在用户输入过程中(或输入后)提供优化建议,解决两大核心问题:
输入效率:通过自动补全减少用户输入量(如搜索框实时联想)。
输入准确性:通过拼写纠错修正用户的错误输入(如“appel”修正为“apple”)。
所有建议器均通过ES的_searchAPI中的suggest字段触发,不影响主查询结果,仅返回建议内容。
2、四大建议器对比
| 建议器类型 | 核心作用 | 适用场景 | 优势 | 关键限制 | 示例 |
|---|---|---|---|---|---|
| Completion | 实时前缀补全 | 搜索框联想 | 速度极快(内存查询) | 仅支持前缀,需专用字段 | 输入“iph” → 联想“iphone 15” |
| Term | 单词拼写纠错 | 单个错词修正 | 逻辑简单,响应快 | 不考虑上下文 | 输入“appel” → 修正为“apple” |
| Phrase | 短语拼写纠错 | 多词短语修正 | 考虑上下文连贯性 | 依赖n-gram,性能略低 | 输入“red appel” → 修正为“red apple” |
| Context Completion | 上下文感知补全 | 带维度筛选的联想 | 支持业务维度过滤 | 需提前定义上下文结构 | 北京地区搜“咖啡” → 联想“北京星巴克” |
二、四种建议器介绍与使用
1. Completion Suggestor(自动补全建议器)
核心作用:针对“实时前缀补全”设计,比如搜索框输入“iph”时,实时返回“iphone”“iphone 15”等结果,速度极快(毫秒级)。
(1)工作原理
基于FST(有限状态转换器)数据结构,将补全候选词提前构建成FST并存储在内存中,而非实时遍历索引。
仅支持前缀匹配(不支持模糊、后缀匹配),需提前定义专用的completion类型字段。
(2)适用场景
- 搜索框实时联想(如电商商品名、新闻标题、APP名称)。
- 需“输入即反馈”的高频交互场景。
(3)关键参数
| 参数 | 说明 | 示例值 |
|---|---|---|
field | 必须是completion类型的字段 | “product_name” |
prefix | 用户输入的前缀(建议内容的匹配依据) | “iph” |
size | 返回的建议数量(默认10) | 5 |
skip_duplicates | 去重相同的建议内容 | true |
(4)使用示例(DSL)
1.第一步:创建索引并定义completion字段
PUT /products
{"mappings": {"properties": {"product_name": {"type": "completion" // 专用补全字段},"price": {"type": "double"}}}
}
2.第二步:插入数据(补全候选词需明确)
POST /products/_doc/1
{"product_name": "iphone 15","price": 5999
}POST /products/_doc/2
{"product_name": "iphone 15 pro","price": 7999
}
3.第三步:发起补全查询(输入“iph”)
GET /products/_search
{"suggest": {"product_suggest": { // 自定义建议名称(可任意)"completion": {"field": "product_name","prefix": "iph","size": 5,"skip_duplicates": true}}}
}
4.返回结果:会在suggest.product_suggest.options中返回“iphone 15”“iphone 15 pro”等建议。
(5)使用实战
目标:实现“输入即联想”的前缀补全(如搜索框实时提示)。
Step 1:创建索引(定义completion字段)
需专门定义 completion 类型字段(底层基于FST存储,优化前缀查询速度)。
PUT /product_suggest # 索引名:商品补全索引
{"mappings": {"properties": {"suggest": { # 补全专用字段(名称可自定义)"type": "completion","analyzer": "ik_smart", # 可选:指定分词器(如中文用IK)"preserve_separators": true, # 保留分隔符(如空格、符号)"preserve_position_increments": true # 保留位置增量(影响分词位置)},"name": { "type": "text" }, # 商品名(非补全用,仅存储)"price": { "type": "double" }}}
}
关键参数:
analyzer:分词器(中文必须指定,如ik_smart;英文默认standard)。
preserve_separators:若为false,会忽略空格(如“iphone 15”和“iphone15”视为同一前缀)。
Step 2:插入数据(定义补全候选词)
补全候选词通过 input 字段指定(支持数组,可添加多个同义词/变体)。
POST /product_suggest/_doc/1
{"name": "iPhone 15 128G","price": 5999,"suggest": {"input": ["iphone 15", "苹果15", "iPhone15"] # 多个候选词,覆盖不同输入习惯}
}POST /product_suggest/_doc/2
{"name": "iPhone 15 Pro 256G","price": 7999,"suggest": {"input": ["iphone 15 pro", "苹果15 Pro"]}
}
Step 3:发起补全查询
通过 prefix 指定用户输入的前缀,获取匹配的候选词。
GET /product_suggest/_search
{"suggest": {"product_complete": { # 自定义建议名称(可任意)"completion": {"field": "suggest", # 关联补全字段"prefix": "iph", # 用户输入的前缀(如搜索框实时输入)"size": 5, # 返回最多5条建议"skip_duplicates": true, # 去重相同建议"fuzzy": { # 可选:允许前缀模糊匹配(如输入“ihp”也能匹配“iph”)"fuzziness": "AUTO" # 自动模糊度(1-2次编辑)}}}}
}
Step 4:解析结果
建议结果在 suggest.product_complete.options 中,包含补全文本和原始文档ID:
{"suggest": {"product_complete": [{"text": "iphone 15","offset": 0,"length": 3,"options": [{ "text": "iphone 15", "_index": "product_suggest", "_id": "1", "score": 1.0 },{ "text": "iphone 15 pro", "_index": "product_suggest", "_id": "2", "score": 1.0 }]}]}
}
2. Term Suggestor(单词拼写纠错建议器)
核心作用:针对单个词的拼写错误提供纠错建议,比如用户输入“appel”时,返回“apple”;输入“teh”时,返回“the”。
(1)工作原理
基于编辑距离(Levenshtein Distance) 计算用户输入词与索引中词的相似度(默认允许最多2次编辑:增、删、改字符)。
仅分析单个词,不考虑词与词的上下文关系。
(2)适用场景
单个关键词的拼写纠错(如“搜索框输入单个错词”“标签输入错误”)。
需快速修正简单输入错误的场景。
(3)关键参数
| 参数 | 说明 | 示例值 |
|---|---|---|
text | 用户输入的错误文本(单个词) | “appel” |
field | 目标字段(需是text/keyword类型) | “product_name” |
suggest_mode | 建议触发模式: - missing:输入词无结果时才建议 - popular:优先建议出现频率高的词 - always:无论是否有结果都建议 | “missing” |
max_edits | 最大编辑距离(1-2,默认2) | 2 |
min_word_length | 最小词长(低于此长度不建议,默认4) | 3 |
(4)使用示例(DSL)
1.前提:使用已有的products索引(product_name为text类型)。
2.发起单词纠错查询(输入“appel”)
GET /products/_search
{"suggest": {"term_suggest": {"text": "appel", // 用户输入的错词"term": {"field": "product_name","suggest_mode": "missing","max_edits": 2,"min_word_length": 3}}}
}
3.返回结果:会在suggest.term_suggest.options中返回“apple”作为建议,并附带相似度得分。
(5)使用实战
目标:修正单个词的拼写错误(如“teh”→“the”)。
Step 1:准备索引(复用现有text字段)
无需专用字段,直接使用已有 text 或 keyword 字段(需确保字段有足够的词项数据)。
PUT /article # 示例:文章索引
{"mappings": {"properties": {"title": { "type": "text", "analyzer": "standard" } # 用于纠错的字段}}
}# 插入测试数据
POST /article/_doc/1
{ "title": "the quick brown fox" }POST /article/_doc/2
{ "title": "apple is a fruit" }
Step 2:发起单词纠错查询
针对用户输入的错误单词(如“appel”“teh”)生成建议。
GET /article/_search
{"suggest": {"term_correction": { # 自定义建议名称"text": "appel", # 用户输入的错误词"term": {"field": "title", # 目标字段"suggest_mode": "missing", # 仅当输入词无结果时建议"max_edits": 2, # 最大编辑距离(1-2,默认2)"min_word_length": 3, # 最短词长(低于此长度不建议)"sort": "frequency" # 按词频排序(默认按相似度)}}}
}
Step 3:解析结果
建议结果包含纠错词、相似度得分和词频:
{"suggest": {"term_correction": [{"text": "appel","offset": 0,"length": 5,"options": [{ "text": "apple", "score": 0.8, "freq": 1 } # freq:词在索引中出现的次数]}]}
}
3. Phrase Suggestor(短语拼写纠错建议器)
核心作用:在Term Suggestor基础上升级,支持多词短语的拼写纠错,且考虑词的上下文和共现频率,比如用户输入“red appel”时,返回“red apple”;输入“the quick brow fox”时,返回“the quick brown fox”。
(1)工作原理
1.第一步:对短语中的每个词单独做Term纠错,生成多个候选词组合。
2.第二步:基于n-gram模型(默认bigram,即2个词的组合)计算候选短语的“合理性”(如“red apple”在索引中出现的频率远高于“red appel”)。
3.第三步:筛选出得分最高的合理短语作为建议。
(2)适用场景
- 多词短语的输入纠错(如“搜索句子”“长标题查询”“商品描述搜索”)。
- 需保证短语语义连贯的场景。
(3)关键参数
| 参数 | 说明 | 示例值 |
|---|---|---|
text | 用户输入的错误短语 | “red appel” |
field | 目标字段(需是text类型,且开启了n-gram分词) | “product_name” |
max_errors | 短语中允许的最大错误词数(默认1) | 1 |
confidence | 置信度(0-1,得分高于此值才返回,默认1) | 0.8 |
gram_size | n-gram的长度(默认2,即bigram) | 2 |
(4)使用示例(DSL)
1.前提:确保product_name字段支持n-gram(若未配置,需先更新映射):
PUT /products/_mapping
{"properties": {"product_name": {"type": "text","analyzer": "standard","fields": {"ngram": { // 新增n-gram子字段"type": "text","analyzer": "ngram_analyzer"}}}},"settings": {"analysis": {"analyzer": {"ngram_analyzer": {"tokenizer": "standard","filter": ["ngram_filter"]}},"filter": {"ngram_filter": {"type": "ngram","min_gram": 2,"max_gram": 3}}}}
}
2.发起短语纠错查询(输入“red appel”)
GET /products/_search
{"suggest": {"phrase_suggest": {"text": "red appel", // 用户输入的错误短语"phrase": {"field": "product_name.ngram", // 使用n-gram子字段"max_errors": 1,"confidence": 0.8,"gram_size": 2}}}
}
3.返回结果:会在suggest.phrase_suggest.options中返回“red apple”作为建议,并附带短语的合理性得分。
(5)使用实战
目标:修正多词短语的拼写错误(如“red appel”→“red apple”),需结合上下文。
Step 1:创建索引(配置n-gram分词)
Phrase依赖n-gram模型计算短语合理性,需提前配置n-gram分词器。
PUT /phrase_corpus # 短语纠错语料库
{"settings": {"analysis": {"analyzer": {"phrase_analyzer": { # 自定义n-gram分析器"tokenizer": "standard","filter": ["lowercase", "ngram_filter"] # 转小写+ngram过滤}},"filter": {"ngram_filter": { # n-gram过滤器(提取2-3个连续字符)"type": "ngram","min_gram": 2,"max_gram": 3}}}},"mappings": {"properties": {"content": { # 用于短语纠错的字段"type": "text","analyzer": "phrase_analyzer"}}}
}# 插入测试短语
POST /phrase_corpus/_doc/1
{ "content": "red apple" }POST /phrase_corpus/_doc/2
{ "content": "the quick brown fox" }
Step 2:发起短语纠错查询
针对错误短语(如“red appel”)生成建议。
GET /phrase_corpus/_search
{"suggest": {"phrase_correction": { # 自定义建议名称"text": "red appel", # 用户输入的错误短语"phrase": {"field": "content", # 目标字段(需n-gram分词)"max_errors": 1, # 允许最多1个错词"confidence": 0.7, # 得分≥0.7才返回(降低可增加建议数量)"gram_size": 2, # 用bigram(2词组合)计算合理性"real_word_error_likelihood": 0.95 # 真实词出错的概率(默认0.95)}}}
}
Step 3:解析结果
建议结果包含修正后的短语及整体得分(得分越高越合理):
{"suggest": {"phrase_correction": [{"text": "red appel","offset": 0,"length": 9,"options": [{ "text": "red apple", "score": 0.85 } # 得分基于bigram共现频率]}]}
}
4. Context Suggestor(上下文感知自动补全建议器)
核心作用:作为Completion Suggestor的扩展,支持按上下文维度过滤补全结果,比如“在‘北京’地区搜‘咖啡’”时,只返回“北京星巴克”“北京瑞幸”,而不返回“上海星巴克”。
(1)工作原理
- 在Completion的FST结构中,为每个补全候选词附加“上下文元数据”(如
category(类别)、location(地区))。 - 查询时指定上下文条件,仅返回匹配该条件的补全结果。
(2)适用场景
- 带维度筛选的自动补全(如电商“分类+关键词”补全、本地生活“地区+服务”补全)。
- 需按业务场景缩小补全范围的场景。
(3)关键参数
| 参数 | 说明 | 示例值 |
|---|---|---|
field | 必须是配置了context的completion字段 | “product_suggest” |
prefix | 用户输入的前缀 | “咖啡” |
contexts | 上下文过滤条件(键为上下文名称,值为过滤值) | {“location”: “北京”} |
(4)使用示例(DSL)
1.第一步:创建带context的completion字段
PUT /local_shops
{"mappings": {"properties": {"shop_name": {"type": "text"},"product_suggest": { // 带上下文的补全字段"type": "completion","contexts": [{"name": "location", // 上下文名称(地区)"type": "category" // 上下文类型(类别型)}]}}}
}
2.第二步:插入带上下文的数据
POST /local_shops/_doc/1
{"shop_name": "北京星巴克","product_suggest": {"input": "星巴克", // 补全候选词"contexts": {"location": "北京" // 附加地区上下文}}
}POST /local_shops/_doc/2
{"shop_name": "上海星巴克","product_suggest": {"input": "星巴克","contexts": {"location": "上海"}}
}
3.第三步:按上下文查询(北京地区搜“星”)
GET /local_shops/_search
{"suggest": {"context_suggest": {"completion": {"field": "product_suggest","prefix": "星","contexts": {"location": "北京" // 仅返回北京地区的“星巴克”}}}}
}
4.返回结果:仅返回“北京星巴克”的补全建议,过滤“上海星巴克”。
(5)使用实战
目标:结合上下文(如地区、类别)过滤补全结果(如“北京+咖啡”只联想本地咖啡店)。
Step 1:创建索引(定义上下文)
在 completion 字段中添加 contexts,支持两种类型:
category:类别型(如地区、分类)。
geo:地理型(如经纬度范围)。
PUT /local_business # 本地商户索引
{"mappings": {"properties": {"business_suggest": { # 带上下文的补全字段"type": "completion","contexts": [{"name": "city", # 上下文名称(城市)"type": "category", # 类别型上下文"path": "city" # 可选:关联文档中的city字段(自动提取上下文值)}]},"name": { "type": "text" },"city": { "type": "keyword" } # 存储城市信息(用于上下文关联)}}
}
Step 2:插入带上下文的数据
通过 contexts 字段指定补全候选词的上下文(如城市)。
POST /local_business/_doc/1
{"name": "星巴克(北京朝阳店)","city": "北京","business_suggest": {"input": ["星巴克", "Starbucks"], # 补全候选词"contexts": { "city": "北京" } # 关联上下文(城市=北京)}
}POST /local_business/_doc/2
{"name": "星巴克(上海浦东店)","city": "上海","business_suggest": {"input": ["星巴克", "Starbucks"],"contexts": { "city": "上海" }}
}
Step 3:按上下文查询
指定 contexts 过滤补全结果(如只查“北京”的星巴克)。
GET /local_business/_search
{"suggest": {"context_complete": {"completion": {"field": "business_suggest","prefix": "星", # 用户输入前缀"contexts": {"city": "北京" # 上下文过滤:只返回北京的结果},"size": 3}}}
}
Step 4:解析结果
仅返回符合上下文条件的补全建议:
{"suggest": {"context_complete": [{"text": "星","offset": 0,"length": 1,"options": [{ "text": "星巴克", "_index": "local_business", "_id": "1", "score": 1.0 }]}]}
}
三、Java高级客户端使用建议器
1. 依赖配置(Maven)
在 pom.xml 中添加 7.10 版本的 High Level REST Client 依赖:
<dependencies><!-- Elasticsearch 核心依赖 --><dependency><groupId>org.elasticsearch</groupId><artifactId>elasticsearch</artifactId><version>7.10.0</version></dependency><!-- High Level REST Client --><dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId><version>7.10.0</version></dependency>
</dependencies>
2. 客户端初始化
创建 RestHighLevelClient 实例(单例模式,避免频繁创建连接):
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;public class EsClient {private static RestHighLevelClient client;// 初始化客户端(连接本地 ES,默认端口 9200)public static RestHighLevelClient getClient() {if (client == null) {client = new RestHighLevelClient(RestClient.builder("localhost:9200" // 若为集群,可添加多个节点:"host2:9200", "host3:9200"));}return client;}// 关闭客户端(程序退出时调用)public static void closeClient() throws IOException {if (client != null) {client.close();}}
}
3.实战场景:商品搜索建议
需求:实现“商品搜索框”功能,包含两个核心能力:
1.输入前缀时实时补全(如输入“iph” → 联想“iphone 15”)。
2.输入错误单词时自动纠错(如输入“appel” → 修正为“apple”)。
Step 1:创建索引(含 Completion 和 Text 字段)
需定义两个关键字段:
suggest:completion 类型,用于自动补全。
name:text 类型,用于 Term 纠错(基于商品名称的词项)。
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.json.JsonXContent;
import java.io.IOException;public class SuggestIndexCreator {public static void createProductIndex() throws IOException {RestHighLevelClient client = EsClient.getClient();// 1. 创建索引请求CreateIndexRequest request = new CreateIndexRequest("product_suggest");// 2. 设置映射(mappings)XContentBuilder mappings = JsonXContent.contentBuilder().startObject().startObject("properties")// Completion 字段:用于自动补全.startObject("suggest").field("type", "completion").field("analyzer", "ik_smart") // 中文分词器(需 ES 安装 IK 插件).field("preserve_separators", true).endObject()// Text 字段:用于 Term 纠错(基于商品名称的词项).startObject("name").field("type", "text").field("analyzer", "standard") // 英文默认分词器.endObject()// 其他字段(如价格).startObject("price").field("type", "double").endObject().endObject().endObject();request.mapping(mappings);// 3. 执行创建请求CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT);if (response.isAcknowledged()) {System.out.println("索引创建成功:product_suggest");} else {System.err.println("索引创建失败");}}public static void main(String[] args) throws IOException {createProductIndex();EsClient.closeClient();}
}
Step 2:插入测试数据
插入包含补全候选词和商品名称的数据:
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.common.xcontent.XContentType;
import java.io.IOException;public class ProductDataInserter {public static void insertData() throws IOException {RestHighLevelClient client = EsClient.getClient();// 数据1:iPhone 15String json1 = "{" +"\"name\": \"iphone 15 128G\"," +"\"price\": 5999," +"\"suggest\": {\"input\": [\"iphone 15\", \"苹果15\", \"iPhone15\"]}" +"}";IndexRequest request1 = new IndexRequest("product_suggest").id("1");request1.source(json1, XContentType.JSON);IndexResponse response1 = client.index(request1, RequestOptions.DEFAULT);System.out.println("插入数据1:" + response1.getId());// 数据2:Apple WatchString json2 = "{" +"\"name\": \"apple watch series 8\"," +"\"price\": 3199," +"\"suggest\": {\"input\": [\"apple watch\", \"苹果手表\"]}" +"}";IndexRequest request2 = new IndexRequest("product_suggest").id("2");request2.source(json2, XContentType.JSON);IndexResponse response2 = client.index(request2, RequestOptions.DEFAULT);System.out.println("插入数据2:" + response2.getId());// 强制刷新索引(确保数据可查)client.indices().refresh(null, RequestOptions.DEFAULT);}public static void main(String[] args) throws IOException {insertData();EsClient.closeClient();}
}
Step 3:集成建议器查询(Completion + Term)
构建包含两种建议的查询请求,同时返回补全结果和纠错建议:
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.search.suggest.Suggest;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.SuggestBuilders;
import org.elasticsearch.search.suggest.completion.CompletionSuggestion;
import org.elasticsearch.search.suggest.term.TermSuggestion;
import java.io.IOException;
import java.util.List;public class ProductSuggestService {/*** 同时获取补全建议和纠错建议* @param userInput 用户输入的文本(如"iph"或"appel")*/public static void getSuggestions(String userInput) throws IOException {RestHighLevelClient client = EsClient.getClient();// 1. 创建搜索请求SearchRequest searchRequest = new SearchRequest("product_suggest");// 2. 构建建议器SuggestBuilder suggestBuilder = new SuggestBuilder();// 2.1 添加 Completion 补全建议(输入前缀联想)CompletionSuggestionBuilder completionSuggestion = SuggestBuilders.completionSuggestion("suggest") // 关联 completion 字段.prefix(userInput) // 用户输入的前缀.size(5) // 返回5条建议.skipDuplicates(true) // 去重.fuzziness(Fuzziness.AUTO); // 允许模糊匹配(如"ihp"匹配"iph")suggestBuilder.addSuggestion("product_completion", completionSuggestion);// 2.2 添加 Term 纠错建议(单词拼写错误修正)TermSuggestionBuilder termSuggestion = SuggestBuilders.termSuggestion("name") // 关联 text 字段(用于纠错).text(userInput) // 用户输入的文本.suggestMode(TermSuggestionBuilder.SuggestMode.MISSING) // 无结果时才建议.maxEdits(2) // 最大编辑距离.sort(TermSuggestionBuilder.Sort.FREQUENCY); // 按词频排序suggestBuilder.addSuggestion("product_term_correction", termSuggestion);// 3. 将建议器添加到搜索请求searchRequest.source().suggest(suggestBuilder);// 4. 执行查询SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);// 5. 解析结果parseSuggestions(response);}/*** 解析建议结果*/private static void parseSuggestions(SearchResponse response) {Suggest suggest = response.getSuggest();// 5.1 解析 Completion 补全建议CompletionSuggestion completionSuggestion = suggest.getSuggestion("product_completion");List<CompletionSuggestion.Entry.Option> completionOptions = completionSuggestion.getOptions();System.out.println("\n===== 补全建议 =====");if (completionOptions.isEmpty()) {System.out.println("无补全建议");} else {for (CompletionSuggestion.Entry.Option option : completionOptions) {System.out.println("补全词:" + option.getText().string() + ",文档ID:" + option.getHit().getId());}}// 5.2 解析 Term 纠错建议TermSuggestion termSuggestion = suggest.getSuggestion("product_term_correction");List<TermSuggestion.Entry.Option> termOptions = termSuggestion.getOptions();System.out.println("\n===== 纠错建议 =====");if (termOptions.isEmpty()) {System.out.println("无纠错建议");} else {for (TermSuggestion.Entry.Option option : termOptions) {System.out.println("纠错词:" + option.getText().string() + ",相似度:" + option.getScore() + ",词频:" + option.getFreq());}}}public static void main(String[] args) throws IOException {// 测试1:输入前缀"iph"(预期补全"iphone 15"等)System.out.println("----- 用户输入:iph -----");getSuggestions("iph");// 测试2:输入错误词"appel"(预期纠错为"apple")System.out.println("\n----- 用户输入:appel -----");getSuggestions("appel");EsClient.closeClient();}
}
执行结果与解析
运行 ProductSuggestService 的 main 方法,输出如下:
----- 用户输入:iph -----===== 补全建议 =====
补全词:iphone 15,文档ID:1
补全词:iPhone15,文档ID:1
补全词:苹果15,文档ID:1===== 纠错建议 =====
无纠错建议 // 因为"iph"在索引中存在对应前缀,无需纠错----- 用户输入:appel -----===== 补全建议 =====
无补全建议 // 因为"appel"不是任何补全词的前缀===== 纠错建议 =====
纠错词:apple,相似度:0.8,词频:1 // 匹配到"apple watch"中的"apple"
关键代码说明
1.SuggestBuilder 构建:
通过 addSuggestion 可添加多个建议器(如同时添加 Completion 和 Term),每个建议器需指定唯一名称(如 product_completion)。
2.Completion 核心参数:
prefix:用户输入的前缀(必选)。
fuzziness(Fuzziness.AUTO):允许一定程度的拼写错误(如“ihp”可匹配“iph”)。
3.Term 核心参数:
suggestMode(MISSING):仅当输入词在索引中无结果时返回建议,避免干扰正确输入。
sort(FREQUENCY):按词在索引中出现的频率排序,优先返回更常见的词。
4.结果解析:
补全结果从 CompletionSuggestion.Option 中获取 text(补全词)和 getHit().getId()(关联文档ID)。
纠错结果从 TermSuggestion.Option 中获取 text(纠错词)、score(相似度)和 freq(词频)。
