java中实现es count distinct

需求

说一下最近项目中碰到的一个es方面的需求:在一个字段columnB里面,获取特定值0的总数据量,
然后在这些数据里面,再做另一个字段columnA的去重并得到该字段值的集合

方案

两种方案写成sql类似如下:

  1. 两次es查询:SELECT COUNT(columnA) from es where columnB = 0;
    SELECT DISTINCT columnA from es where columnB = 0;
  2. 一次es查询:SELECT columnA, COUNT(columnA) from es where columnB = 0 group by columnA,然后在代码中对COUNT(columnA)进行sum;

说实话,最初lz对es的聚合方法是不太熟悉的,只能借鉴前人的经验(Google、百度)去快速了解详情,于是有了以下:
cardinality:先去重再求和,显然不符合需求;
terms:group by,可以嵌套aggs进行stats统计;
stats:一次性获取count max min avg sum 5个值;
Extended stats:比stats多4个统计结果: 平方和、方差、标准差、平均值加/减两个标准差的区间。

可惜时间比较仓促,花了一两天时间也没有摸索出一次es查询相应的Java代码,所以按照两次查询(1.2+2.2)去实现的(幸好是es,查询速度不慢)
1.想要分组、或者说distict并count,有两种方法:
1.1 AggregationBuilders.terms方法(初看高精尖,类似于sql里的group by),配合以下使用获取count;
Terms.Bucket bucket = searchResponse.getAggregations().get(“自定义名字1”).getBucketByKey(0);
long count = bucket.getAggregations().get(“自定义名称2”).getCount();
1.2 QueryBuilders.matchPhraseQuery方法(不分词匹配,初看比较low,因为lz用过太多次)配合以下使用获取count;
long count = searchResponse.getHits().getHits().length

2.想要去重并得到字段值的集合,也有两种方法:top_hits(默认size<100)聚合和collapse(默认size<10000)
2.1 AggregationBuilders.terms(…).subAggregation(AggregationBuilders.topHits(…));
searchSourceBuilder.aggregation(aggregation);
—弊端:1.topHits中的字段都会被拿出来,并没有去重,如果总数据量很大,这样的结果是灾难性的;2.默认可以取出的数量100,可能将来达不到项目需求
2.2 CollapseBuilder collapseBuilder = new CollapseBuilder(字段名 + “.keyword”);// .keyword只针对"type": "keyword"的字段
searchSourceBuilder.collapse(collapseBuilder);
—弊端:1.只能跟第二种分组方法配合,并且要两次搜索(先count后DISTINCT);2.默认可以取出的数量10000应该能达到项目目前的需求

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值