Elasticsearch查询以及聚合查询

本文介绍了Elasticsearch中bool查询的使用,包括must、filter、should和must_not子句的含义。接着讲解了如何过滤不存在的字段数据以及统计字段出现次数。进一步讨论了exists用于过滤字段不存在的数据。最后,文章详细探讨了聚合查询,如分组查询、多条件聚合以及如何通过java代码处理聚合查询结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、条件查询 bool

must:返回的文档必须满足子句的条件,并且参与计算分值
filter:返回的文档必须满足filter子句的条件,不会参与计算分值
should:返回的文档可能满足should子句的条件。
must_nout:返回的文档必须不满足must_not定义的条件。
注意:如果一个查询既有filter又有should,那么至少包含一个should子句。

bool 查询

user 值为kimchy tag 值为tech

"query": {
   "bool" : {
        "must" : {
            "term" : { "user" : "kimchy" }
        },
        "filter": {
            "term" : { "tag" : "tech" }
        },
        "must_not" : {
            "range" : {
                "age" : { "from" : 10, "to" : 20 }
            }
        },
        "should" : [
            {"term" : { "tag" : "wow" }},
            {"term" : { "tag" : "elasticsearch" }}
        ]
    }

过滤不存在数据

"query": {
        "bool":{
            "filter":{
                "exists":{
                    "field":"subject" }
            }
        }   
    }

统计某个字段出现的次数

size 0 不需要返回文档数据,只需要值

  "size": 0,
   "query": {
        "bool":{
            "filter":{
                "exists":{
                    "field":"proofreadresult" }
            }
        }   
    }

返回 某个字段 ischeck值为false 的数量

"size": 0,
   "query": {
        "bool":{
            "must": [{"match": {"ischeck": "false"}}],
        }   
    }
}

"size": 0,
   "query": {
        "bool":{
            "must":  {"term" : { "ischeck" : "false" }}
        }   
    }
}

返回的数据 value 就是我们需要的数据

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 3476,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  }
}

2、字段过滤
过滤字段不存在的数据,filter + exists

使用 exists 进行过滤掉字段不存在的数据

 "size": 0, 
 "query": {
        "bool":{
            "filter":{"exists":{"field":"subject" }},
             "must": [{"range": {"createtime": {
                      "gte": 1654012800000,
                      "lte": 1655308799000}}
                     }]
         }   
 }

3、聚合查询
1)分组 https://blog.youkuaiyun.com/cainiao1412/article/details/120876972
聚合分组查询,使用terms,按照某个字段中的值来分类,通过size的值来确定返回文档的数量,如果不指定值,默认返回10个
Es query 中,使用 term 进行精准查询,不会对字段进行分词,
使用terms,进行多个条件查询,类似 in

使用 script 进行多个字段 分组的实现,通过需要自己进行split处理

对uid进行分组

 "aggs": {
        "result": {
            "terms": {
                "field": "uid",
                "size": 2147483647
            } 
        }
  }

对 uid+subject 进行分组 通过 size 指定大小

"aggs": {
        "result": {
            "terms": {
                "script": { "inline": "doc['uid'].value +'-'+ doc['subject'].value"},
                "size": 40
            }
        }
  }

2)聚合查询先进行过滤,然后分组

size 表示query返回的数据

subject 存在的数据中 按照 uid-subject 分组数据

  "size": 0,
  "aggs": {
    "filer-subject" : {
      "filter": {
        "bool" : {
          "filter" : [
            {"exists":{"field":"subject"}}
          ]
        }
      },
      "aggs": {
        "result" : {
            "terms": {
                "script": { "inline": "doc['uid'].value +'-'+ doc['subject'].value"},
                "size": 40
            } 
        }
      }
    }
  }
``

  # 返回的数据
  

```bash
 "aggregations" : {
    "filer-subject" : {
      "doc_count" : 3557,
      "result" : {
        "doc_count_error_upper_bound" : 0,
        "sum_other_doc_count" : 988,
        "buckets" : [
          {
            "key" : "209372605317121-102",
            "doc_count" : 794
          },
          {
            "key" : "222580707950593-302",
            "doc_count" : 447
          },
          {
            "key" : "212246483697665-102",
            "doc_count" : 374
          },
          {
            "key" : "207843605348353-102",
            "doc_count" : 328
          }]
}}

对应的java代码

Script script = new Script(ScriptType.INLINE,Script.DEFAULT_SCRIPT_LANG , "doc['uid'].value+'-'+doc['subject'].value", new HashMap<>());
        TermsAggregationBuilder aggregationBuilder = AggregationBuilders.terms("result").script(script).size(ESCommonConstant.ES_GROUP_QUERY_SIZE);
        // search
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.aggregation(aggregationBuilder);
        // query
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        List<QueryBuilder> must = boolQueryBuilder.must();

        if(Objects.nonNull(requestDWDProofreadRecordDTO.getStartTime()) && Objects.nonNull(requestDWDProofreadRecordDTO.getEndTime())){
             must.add(QueryBuilders.rangeQuery(ProofreadDetailConstant.CREATETIME).from(requestDWDProofreadRecordDTO.getStartTime()).to(requestDWDProofreadRecordDTO.getEndTime()));
        }
        must.add(QueryBuilders.boolQuery().must((QueryBuilders.existsQuery("subject"))));

        searchSourceBuilder.query(boolQueryBuilder);
        searchSourceBuilder.size(0);

3)聚合多条件查询,并按指定的文档返回想要的数据

"size": 0,
  "aggs": {
  # 该数据是  条件 ischeck 值为true,subject 存在,
  # 分组 combinequestiontype分组返回总数量
    "ischeck-count" : {
      "filter": {
        "bool" : {
          "filter" : [
            {"exists":{"field":"subject"}} 
          ],
          "must" : {"term" : {"ischeck" : "true"} }  
        } 
      },
      "aggs": {
        "result" : {
            "terms": {
                "field": "combinequestiontype",
                "size": 30
            } 
        }
        
      }
    },

  # 该数据是 条件 proofreadresult存在,
  # 分组 combinequestiontype分组返回总数
  "proofreadresult-count" : {
      "filter": {
        "bool" : {
          "filter" : [
            {"exists":{"field":"proofreadresult"}} 
          ] 
        } 
      },
      "aggs": {
        "result" : {
            "terms": {
                "field": "combinequestiontype",
                "size": 30
            } 
        }
        
      }
    },
    

  # 该数据是 返回 isCheck 的数量
  "ischeck_total": {
        "terms": {
          "field": "ischeck"
        }
     },
 
   # 该数据是 返回 proofreadresult 字段存在 的数量
   # 即就是 proofreadresult  不为空的数量
 "proofreadresult_total": {
        "filter": {
              "bool" : {
                "filter" : [
                    {"exists":{"field":"proofreadresult"}} 
                  ] 
              } 
        }
     }
  }

对应的java代码

// ischeck-count
        FilterAggregationBuilder ischeckCount = AggregationBuilders.filter("ischeck-count", QueryBuilders.boolQuery()
                .must(QueryBuilders.termQuery("ischeck", true))
                .must(QueryBuilders.termQuery("uid", uid))
                .filter(QueryBuilders.existsQuery("xxx")))
                .subAggregation(AggregationBuilders.terms("result").field("xxx").size(30));

        // proofreadresult-count
        FilterAggregationBuilder proofreadCount = AggregationBuilders.filter("ischeck-count", QueryBuilders.boolQuery()
                .must(QueryBuilders.termQuery("ischeck", true))
                .must(QueryBuilders.termQuery("uid", uid))
                .filter(QueryBuilders.existsQuery("xxx")));

        searchSourceBuilder.aggregation(ischeckCount);

// 结果处理
List list = new ArrayList<>();
SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
Terms oneTerm = (Terms) response.getAggregations().asMap().get(“result”);
for (Terms.Bucket bucket : oneTerm.getBuckets()) {
ProofreadDetailDTO proofreadDetailDTO = new ProofreadDetailDTO();
// 此处自己split分隔处理
String[] strings = bucket.getKey().toString().split(“-”);
proofreadDetailDTO.setUid(Long.parseLong(strings[0]));
proofreadDetailDTO.setSubject(Integer.parseInt(strings[1]));
list.add(proofreadDetailDTO);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值