Elasticsearch Java API查询无法返回期望文档结果的解决求助
问题:Elasticsearch查询无法返回期望的文档结果
背景信息
使用Elasticsearch时,编写了以下DSL查询:
{ "query": { "bool": { "must": [ {"match": { "companyId": 35 }}, { "multi_match": { "query": "movie", "fields": ["name", "description"] } } ] } } }
基于该DSL构建的Java QueryBuilder代码:
SearchRequest searchRequest = new SearchRequest("faqs");//index name SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); QueryBuilder mulMatch = QueryBuilders.multiMatchQuery(name,"name", "description").type("phrase").boost(5); QueryBuilder cId = QueryBuilders.matchQuery("companyId", companyId).boost(5); QueryBuilder must = QueryBuilders.boolQuery().must(cId).must(mulMatch).boost(5); searchSourceBuilder.query(must); searchRequest.source(searchSourceBuilder); System.out.println("SS Query : " + searchSourceBuilder); return searchSourceBuilder;
生成的实际查询语句:
{"query":{"bool":{"must":[{"match":{"companyId":{"query":35,"operator":"OR","prefix_length":0,"max_expansions":50,"fuzzy_transpositions":true,"lenient":false,"zero_terms_query":"NONE","auto_generate_synonyms_phrase_query":true,"boost":5.0}}},{"multi_match":{"query":"movie","fields":["description^1.0","name^1.0"],"type":"phrase","operator":"OR","slop":0,"prefix_length":0,"max_expansions":50,"zero_terms_query":"NONE","auto_generate_synonyms_phrase_query":true,"fuzzy_transpositions":true,"boost":5.0}}],"adjust_pure_negative":true,"boost":5.0}}}
期望返回的文档格式:
{ "Id": 1, "name": "Controle", "description": "Welcome movie", "visibility": "2", "isarticleEnabled": false, "companyId": 35, "categoryId": 0 }
但实际API返回结果为:
{ "suggestOnly": false, "fragment": false }
尝试使用SearchResponse res = client.search(searchRequest, RequestOptions.DEFAULT);,但在ElasticsearchRestTemplate和RestHighLevelClient中均无法正常获取期望结果。
解决方案
1. 修正结果解析逻辑
当前返回的{"suggestOnly": false, "fragment": false}属于高亮或建议组件的返回片段,并非完整的搜索文档。需要检查代码中是否错误提取了高亮片段,而非从搜索命中结果中获取原始文档。
2. RestHighLevelClient正确解析示例
如果使用RestHighLevelClient,需从SearchResponse中提取命中的文档数据:
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT); SearchHit[] hits = response.getHits().getHits(); List<Map<String, Object>> resultDocs = new ArrayList<>(); for (SearchHit hit : hits) { // 获取文档原始数据 Map<String, Object> source = hit.getSourceAsMap(); resultDocs.add(source); // 如需转换为实体类,可使用ObjectMapper // YourEntity entity = new ObjectMapper().readValue(hit.getSourceAsString(), YourEntity.class); }
3. ElasticsearchRestTemplate正确使用示例
如果使用ElasticsearchRestTemplate,需通过SearchHits提取实体对象:
// 构建SearchQuery NativeSearchQuery searchQuery = new NativeSearchQueryBuilder() .withQuery(must) .build(); // 执行查询并解析结果 SearchHits<YourEntity> searchHits = elasticsearchRestTemplate.search(searchQuery, YourEntity.class); List<YourEntity> resultEntities = searchHits.stream() .map(SearchHit::getContent) .collect(Collectors.toList());
4. 验证查询本身的有效性
先通过Kibana或curl执行生成的DSL,确认Elasticsearch中存在匹配的文档:
curl -X GET "localhost:9200/faqs/_search" -H "Content-Type: application/json" -d ' {"query":{"bool":{"must":[{"match":{"companyId":{"query":35,"operator":"OR","prefix_length":0,"max_expansions":50,"fuzzy_transpositions":true,"lenient":false,"zero_terms_query":"NONE","auto_generate_synonyms_phrase_query":true,"boost":5.0}}},{"multi_match":{"query":"movie","fields":["description^1.0","name^1.0"],"type":"phrase","operator":"OR","slop":0,"prefix_length":0,"max_expansions":50,"zero_terms_query":"NONE","auto_generate_synonyms_phrase_query":true,"fuzzy_transpositions":true,"boost":5.0}}],"adjust_pure_negative":true,"boost":5.0}}}'
- 如果该查询能返回期望文档,说明问题出在Java代码的结果解析环节;
- 如果无结果返回,需检查:
multi_match使用了phrase类型,需确认name或description字段中存在完整的"movie"短语(而非分词后的单个词);companyId字段的映射类型是否为数值型(integer/long),避免类型不匹配导致查询失效。
内容的提问来源于stack exchange,提问作者Parva Gurav
相关产品推荐
相关产品推荐

