elasticSearch之API:建议器(suggest)
ES建议器本质是通过“预计算”或“实时相似度匹配”,在用户输入过程中(或输入后)提供优化建议,解决两大核心问题:输入效率:通过自动补全减少用户输入量(如搜索框实时联想)。输入准确性:通过拼写纠错修正用户的错误输入(如“appel”修正为“apple”)。所有建议器均通过ES的_searchAPI中的suggest字段触发,不影响主查询结果,仅返回建议内容。核心作用:针对“实时前缀补全”设计,比如搜
文章目录
一、建议器简介
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 15
String 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 Watch
String 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(词频)。
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)