Elasticsearch Search Java API查询无结果,Kibana同名查询正常
问题分析:Elasticsearch Java API Term查询无结果但Kibana查询正常
先看你提供的Java API查询代码:
RestHighLevelClient client = new RestHighLevelClient( RestClient.builder( new HttpHost("localhost", 9200, "http"))); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); qb = QueryBuilders.termQuery("title", "Java"); searchSourceBuilder.query(qb); searchSourceBuilder.from(0); searchSourceBuilder.size(5); SearchRequest searchRequest = new SearchRequest("myindex"); searchRequest.types("books"); searchRequest.source(searchSourceBuilder); SearchResponse sr = client.search(searchRequest); System.out.println(sr.getHits().totalHits);
以及Kibana中能正常返回结果的查询:
GET /myindex/books/_search { "query": { "term" : { "title" : { "value" : "java" } } } }
问题原因
这是典型的Term查询精确匹配特性和Elasticsearch默认文本分词行为冲突导致的:
- Term查询是严格的精确匹配,它会直接去索引里找和查询值完全一致的词条
- Elasticsearch默认的
standard分词器处理文本字段时,会自动把所有字母转换为小写。也就是说你存储的文档中,title字段被索引成了小写的java,而不是你可能以为的原始大小写形式 - 你在Java代码里查询的是大写开头的
Java,和索引里实际存储的java不匹配,所以返回空结果;而Kibana里用的是全小写的java,刚好和索引里的词条完全一致,所以能查到数据
解决办法
你可以根据自己的业务需求选择以下方案:
- 最简单的修复:把Java代码里的查询值改成小写:
QueryBuilders.termQuery("title", "java"),这样就能和索引里的精确值匹配 - 如果需要支持大小写不敏感的模糊查询:改用
match查询,它会使用和索引时相同的分词器处理查询值,默认支持大小写不敏感:QueryBuilders.matchQuery("title", "Java") - 如果需要保留原始大小写的精确查询:修改
title字段的映射,添加一个keyword类型的子字段(比如title.keyword),然后查询这个子字段:QueryBuilders.termQuery("title.keyword", "Java")(前提是你存储的文档里title确实是Java这种形式)
内容的提问来源于stack exchange,提问作者Mandroid
相关产品推荐
相关产品推荐

