我是靠谱客的博主 想人陪冬瓜,最近开发中收集的这篇文章主要介绍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应该能达到项目目前的需求

最后

以上就是想人陪冬瓜为你收集整理的java中实现es count distinct需求的全部内容,希望文章能够帮你解决java中实现es count distinct需求所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(54)

评论列表共有 0 条评论

立即
投稿
返回
顶部