Elasticsearch 7.X 基于上下文的自动补全功能Java实现报错求助
看起来你遇到的问题主要来自三个方面:API使用错误、上下文key设置不对,以及请求对象的重复创建。让我一步步帮你修正:
1. 核心错误:找不到ContextBuilder类
你看到的MissingPropertyException是因为要么没有导入正确的ContextBuilder类,要么使用了错误的API语法。
在Elasticsearch High Level Rest Client(7.x+版本)中,ContextBuilder的正确全限定名是org.elasticsearch.search.suggest.completion.context.ContextBuilder,首先确保你已经导入了这个类:
import org.elasticsearch.search.suggest.completion.context.ContextBuilder
另外,你之前构建上下文的语法有误:ContextBuilder.category("lang").field("lang")是错误的,正确的方式是先指定上下文类型(category),再设置对应的值,上下文的名称是在添加到建议器时指定的。
2. 上下文映射的key设置错误
你的DSL查询中上下文名称是lang,但代码里把prefLang(比如"en")作为map的key,这会导致Elasticsearch无法识别对应的上下文字段。正确的做法是用上下文名称(lang)作为key,或者更推荐直接使用CompletionSuggestionBuilder的addContext方法,这样更直观。
3. 重复创建SearchRequest导致索引未设置
你代码里先创建了searchRequest并指定了索引,但之后又新建了一个未设置索引的request,这会导致请求发送到错误的索引(或所有索引),进而失败。
修正后的完整代码
// 确保导入了正确的类 import org.elasticsearch.search.suggest.SuggestBuilder import org.elasticsearch.search.suggest.SuggestBuilders import org.elasticsearch.search.suggest.completion.CompletionSuggestionBuilder import org.elasticsearch.search.suggest.completion.context.ContextBuilder import org.elasticsearch.action.search.SearchRequest import org.elasticsearch.action.search.SearchResponse import org.elasticsearch.search.SearchSourceBuilder import org.elasticsearch.client.RequestOptions // 构建补全建议器 CompletionSuggestionBuilder completionSuggestion = SuggestBuilders.completionSuggestion("name_suggest") .text(term) // 添加lang上下文,名称是"lang",值为你的prefLang(比如"en") .addContext("lang", ContextBuilder.category().value(prefLang).build()) SuggestBuilder sb = new SuggestBuilder() sb.addSuggestion("completeMe", completionSuggestion) SearchSourceBuilder sourceBuilder = new SearchSourceBuilder() // 注意:你的DSL里没有query部分,如果不需要可以去掉这行 // sourceBuilder.query(query) sourceBuilder.suggest(sb) // 只创建一次SearchRequest并指定索引 SearchRequest searchRequest = new SearchRequest(AUTOCOMPLETE_TERMS_ALIAS + "_v4") searchRequest.source(sourceBuilder) // 执行查询 SearchResponse suggestResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT) // 处理结果 int count = 5 Suggest.Suggestion<?> suggestion = suggestResponse.getSuggest().getSuggestion("completeMe") if (suggestion != null && !suggestion.getEntries().isEmpty()) { for (Suggest.Suggestion.Entry.Option option : suggestion.getEntries().get(0).getOptions()) { if (count <= 0) break count-- String text = option.getText().string() result.getOptions().add(new AutocompleteResult.SuggestOption(text)) if (log.isTraceEnabled()) { log.trace("Got suggestion: {}", text) } } }
额外检查
还要确认你的索引映射中,name_suggest字段的completion类型已经正确配置了lang上下文,比如:
{ "mappings": { "properties": { "name_suggest": { "type": "completion", "contexts": [ { "name": "lang", "type": "category" } ] } } } }
这样修改后,你的Java代码应该就能和Kibana里的DSL查询一样正常工作了。
内容的提问来源于stack exchange,提问作者R2D2

