如何用Elasticsearch Rest High Level Client实现任意字段关键词搜索?
解决Elasticsearch 6.2.4 Rest High Level Client搜索含关键词合同的问题
我来帮你修正代码并实现这个功能,先梳理下你原代码里的几个核心问题:
termQuery的第一个参数是空字符串,这会让Elasticsearch完全不知道要搜索哪个字段;而且termQuery是精确匹配,如果你的合同内容是text类型的全文字段,用它搜关键词大概率得不到预期结果,应该用matchQuery或multiMatchQuery来做全文搜索。- 另外提个小建议:
RestHighLevelClient实例最好不要每次请求都创建后关闭,实际项目里通常会把它做成单例复用(比如Spring项目里配置成Bean),不过你用try-with-resources管理的写法本身是没问题的。
下面是修正后的完整代码,我加了详细注释方便你理解:
import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.index.query.MatchQueryBuilder; import org.elasticsearch.search.builder.SearchSourceBuilder; import org.elasticsearch.search.SearchHit; import java.io.IOException; import java.util.Collection; import java.util.LinkedList; import java.util.Map; public Collection<Map<String, Object>> findContractsByWord(String index, String type, String word) throws CommonUserException { // 1. 初始化搜索请求,指定目标索引和文档类型(6.x版本支持type,7.x开始弃用) SearchRequest searchRequest = new SearchRequest(index); searchRequest.types(type); // 2. 构建搜索逻辑 SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); // 用matchQuery做全文搜索,第一个参数替换成你实际要搜索的字段名(比如"content"合同正文、"title"合同标题) MatchQueryBuilder matchQuery = QueryBuilders.matchQuery("content", word); sourceBuilder.query(matchQuery); // 可选:默认返回10条结果,如果需要更多可以调整数量 // sourceBuilder.size(50); searchRequest.source(sourceBuilder); SearchResponse searchResponse; try (RestHighLevelClient client = getClient()) { // 执行搜索请求 searchResponse = client.search(searchRequest); } catch (IOException e) { // 把异常详情传入,方便后续排查问题 throw new CommonUserException("Elasticsearch搜索异常", e.getMessage()); } // 3. 解析搜索结果,提取合同数据 SearchHit[] hits = searchResponse.getHits().getHits(); Collection<Map<String, Object>> contracts = new LinkedList<>(); for (SearchHit hit : hits) { // 获取文档的源数据,也就是你存储的合同内容 contracts.add(hit.getSourceAsMap()); } return contracts; }
补充几个实用的扩展说明:
- 如果需要同时搜索多个字段(比如合同标题、正文、甲方名称),可以用
multiMatchQuery替代matchQuery:sourceBuilder.query(QueryBuilders.multiMatchQuery(word, "title", "content", "party_a")); - 如果你要搜索的是精确值(比如合同编号),才适合用
termQuery,记得指定正确的字段名:QueryBuilders.termQuery("contract_no", word);
内容的提问来源于stack exchange,提问作者driveall
相关产品推荐
相关产品推荐

