Es聚合查询,对Object类型进行聚合分组查询

Es聚合查询,对Object类型进行聚合分组查询

平常在es中查询都是精确查询,当某个值等于某个值的时候,例如

BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.must(QueryBuilders.termQuery("status", 3));

有时不知道字段的精确值,或是想要使用类似mysql中的group by 操作,就需要使用聚合查询,聚合查询又有求最大值、最小值、排序和分组等。
例如想要在person中查询age字段的最大值

GET /person/_search
{
 "aggregations": {
  "max_age": {
   "max": {
    "field": "age"
   }
  }
 }
}

java代码

@Autowired
private RestHighLevelClient client;
 
@Test
public void maxQueryTest() throws IOException {
 // 聚合查询条件
    AggregationBuilder aggBuilder = AggregationBuilders.max("max_age").field("age");
    SearchRequest searchRequest = new SearchRequest("person");
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    // 将聚合查询条件构建到SearchSourceBuilder中
    searchSourceBuilder.aggregation(aggBuilder);
    System.out.println("searchSourceBuilder----->" + searchSourceBuilder);
 
    searchRequest.source(searchSourceBuilder);
    // 执行查询,获取SearchResponse
    SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
    System.out.println(JSONObject.toJSON(response));
}

es中的聚合分组查询,类似于Mysql中的group by操作

http://localhost:9200/your_index/_search
{
  "size": 0, 
  "aggs": {
    "aggs_tag":{
      "terms": {
        "field": "id",
        "order": {
          "_count": "desc"
        }
      }
    }
  },
  "query":{"term":{"batchId":"174268241231"}}
}

响应如下:

{
    "took": 29,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 5,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": 12,
        "max_score": 0.0,
        "hits": []
    },
    "aggregations": {
        "aggs_tag": {
            "doc_count_error_upper_bound": 0,
            "sum_other_doc_count": 2,
            "buckets": [
                {
                    "key": 1645123213121232,
                    "doc_count": 2
                },
                {
                    "key": 1645123213121233,
                    "doc_count": 2
                },
                {
                    "key": 1645123213121234,
                    "doc_count": 1
                },
                {
                    "key": 1645123213121235,
                    "doc_count": 1
                },
                {
                    "key": 1645123213121241,
                    "doc_count": 1
                }
            ]
        }
    }
}

但是es中的对象类型该如何查询呢,例如

{
    "id":"1645123213121241",
    "businessId":"17426824093424234",
    "labels":{
        "满意度回访":"1分",
        "打分评价":"2分"
    },
    "batchType":"0",
    "time":"2023-11-11 19:24:50",
}

这时要想对Labels中的某一字段进行分组查询,使用上述的请求 labels或者labels.满意度回访都不能得到结果
es中本身没有对象的概念,存储为object时,es会将对象平铺展开,即

labels.满意度回访:1分
labels.打分评价:2分

这时请求应为

{
  "size": 0, 
  "aggs": {
    "aggs_tag":{
      "terms": {
        "field": "labels.满意度回访.keyword",
        "order": {
          "_count": "desc"
        }
      }
    }
  },
  "query":{"term":{"batchId":"17426824093424234"}}
}

得到响应

{
    "took": 189,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 5,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": 12,
        "max_score": 0.0,
        "hits": []
    },
    "aggregations": {
        "aggs_tag": {
            "doc_count_error_upper_bound": 0,
            "sum_other_doc_count": 0,
            "buckets": [
                {
                    "key": "1分",
                    "doc_count": 3
                },
                {
                    "key": "2分",
                    "doc_count": 1
                }
            ]
        }
    }
}

java代码为

String label = "your_label";
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
TermsAggregationBuilder aggBuilder = AggregationBuilders.terms(label+"_count").field("labels."+label+".keyword").size(20);
searchSourceBuilder.aggregation(aggBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = client.search(searchRequest);

这时有一个很头疼的问题,得到的响应该如何处理呢,debug很久都没有拿到这个bulket桶对象,这时需要一个Terms对象强转然后用Terms.Bucket接收

Map<String, Integer> map = new HashMap<>();
List<? extends Terms.Bucket> lbucket = ((Terms) searchResponse.getAggregations().asMap().get(label + "_count")).getBuckets();
for (Terms.Bucket l : lbucket) {
    map.put(l.getKeyAsString(), (int) l.getDocCount());
}
return map;
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值