javaAPI实现elasticsearch5.5.2的聚合分析
来源:互联网 发布:淘宝纯露哪家比较好 编辑:程序博客网 时间:2024/05/18 00:28
前言:
在前面的几篇文章讲到了elasticsearch的搜索,但是elasticsearch还有强大的聚合分析功能,通过聚合,我们会得到一个数据的概览,这样对大数据提取统计指标时就变得游刃有余。聚合允许我们向数据提出一些复杂的问题。虽然功能完全不同于搜索,但它们使用相同的数据结构,执行速度很快并且就像搜索一样几乎是实时的。
一、聚合(Aggregations)的介绍
elasticsearch的聚合(Aggregations)类似于数据库sql中的分组 group by,count、sum等函数,除此之外他还有更多强大的数据统计分析接口。
聚合有两个核心概念:
1.桶(bucket):对数据进行分组。比如一个对象User他有一个属性是city,有如下数据:1.张三 上海 ;2.李四 北京; 3.王五 北京,我们就可以基于city划分buckets,一个是北京bucket,一个是上海bucket,按照某个字段进行bucket划分,那个字段的值相同的那些数据,就会被划分到一个bucket中,相当于sql中的group by分组。
2.指标(metric):对一个数据分组执行的统计。当我们有了一堆bucket之后,就可以对每个bucket中的数据进行聚合分词了,比如说计算一个bucket内所有数据的数量、平均值、最大值等的,metric就是对一个bucket执行的某种聚合分析的操作,相当于数据库中的avg,sum函数
二、Bucket aggregations 聚合分组的使用
官方参考资料:
https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/_bucket_aggregations.html
我会在第一个例子中将完整的代码写出来,其他的例子仿照第一个进行
1. Terms Aggregation
terms按照某个字段进行分组,下面的代码中也涉及了排序问题,详细代码看注释
/**TermAggs 包含了Order * termAggs统计每个颜色的个数* @Title: countByColor * @Description: TODO(统计每个颜色的销量) * @param @throws UnknownHostException* @return void* @autor lpl* @date 2017年11月6日* @throws */@Testpublic void countByColor() throws UnknownHostException{//进行聚合查询,terms按照某个字段中进行分组TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms("popular_colors")//aggs的名称,自定义,取数据的时候与其一致即可.field("color")//需要分组的字段//.order(Terms.Order.term(true))//true表示按照term分组的asc排序.order(Terms.Order.count(true)); //true表asc按照doc_count排序,false表示desc排序//查询数据进行聚合分析SearchResponse response = EsClient.client().prepareSearch("tvs").setTypes("sales").addAggregation(termsAggregationBuilder).setSize(0).execute().actionGet();//获取聚合Terms terms = response.getAggregations().get("popular_colors");//遍历处理数据for (Terms.Bucket entry : terms.getBuckets()) {Map<String,Object> map = new HashMap<String,Object>(); String key = (String) entry.getKey(); // Term long docCount = entry.getDocCount(); // Doc count //将结果放到Map中map.put("color",key);map.put("docCount",docCount);System.out.println(map);}}
在Terms Aggregation涉及到一个Order分组问题,在上面的代码上我已经做了简单的注释,但是还存在一种排序方式,就是我们按照某一个统计出来字段进行排序,比如:按照height字段的平均值进行排序,fasle代表了desc排序
AggregationBuilders .terms("genders") .field("gender") .order(Terms.Order.aggregation("avg_height", false)) .subAggregation( AggregationBuilders.avg("avg_height").field("height") )
2. Histogram Aggregation 按照区间进行分组
按照区间分组有Histogram Aggregation 和 Date Histogram Aggregation,我们以两个简单的需求进行编写具体的代码
2.1Histogram Aggregation:以2000位区间单位统计电视的销量
/** * 以2000位区间单位统计电视的销量* @Title: HistogramTest * @param @throws UnknownHostException* @return void* @autor lpl* @date 2017年11月6日* @throws */@Testpublic void HistogramTest() throws UnknownHostException{//histogram:类似于terms,也是进行bucket分组操作,interval:2000,//划分范围,0~2000,2000~4000,4000~6000,6000~8000,8000~10000HistogramAggregationBuilder histogramAggregationBuilder = AggregationBuilders.histogram("his_price").field("price").interval(2000);//查询数据进行聚合分析SearchResponse response = EsClient.client().prepareSearch("tvs").setTypes("sales").addAggregation(histogramAggregationBuilder).setSize(0).execute().actionGet();Histogram agg = response.getAggregations().get("his_price");// For each entryfor (Histogram.Bucket entry : agg.getBuckets()) {Map<String,Object> map = new HashMap<String,Object>(); Number key = (Number) entry.getKey(); // 区间key long docCount = entry.getDocCount(); // Doc count //数据封装 map.put("key",key); map.put("doc_count",docCount); System.out.println(map);}}2.2Date Histogram Aggregation:统计每个月份的电视销量,这个需求中还涉及了一些其他知识点,在代码注释中有体现
/** * 统计每个月份的电视销量* @Title: dateHistogramTest * @Description: TODO(这里用一句话描述这个方法的作用) * @param @throws UnknownHostException* @return void* @autor lpl* @date 2017年11月6日* @throws */@Testpublic void dateHistogramTest() throws UnknownHostException{//Date histogram的用法与histogram差不多,只不过区间上支持了日期的表达式。DateHistogramAggregationBuilder dateHistogramInterval = AggregationBuilders.dateHistogram("date_hist")//聚合的名称,可以随意去取,下边取数据一致即可.field("sold_date")//需要进行分组的字段.dateHistogramInterval(DateHistogramInterval.MONTH)//设置时间区间.minDocCount(0)//设置最小的 doc_count,.format("yyyy-MM-dd")//将返回的时间结果进行格式化.missing("2016-05-01");//缺省字段:当遇到没有值的字段,就会按照该字段的值来计算//查询数据进行聚合分析SearchResponse response = EsClient.client().prepareSearch("tvs").setTypes("sales").addAggregation(dateHistogramInterval).setSize(0).execute().actionGet();//获得我们设置的聚合Histogram agg = response.getAggregations().get("date_hist");//循环数据输出for (Histogram.Bucket entry : agg.getBuckets()) {Map<String,Object> map = new HashMap<String,Object>();//处理DateTime key = (DateTime) entry.getKey(); // Key String keyAsString = entry.getKeyAsString(); // Key as String long docCount = entry.getDocCount(); // Doc count //封装 map.put("date",keyAsString); map.put("doc_count",docCount); System.out.println(map);}}3.Range Aggregation按照范围进行分组
这个功能介绍中,我会减少代码量,只把关键代码贴出来,代码中会有注释
3.1.数字范围:
AggregationBuilder rangAgg = AggregationBuilders.range("rang_price").field("price").addUnboundedTo(1000)//从负无穷到1000.addRange(1001, 1500)//从1001-1500.addRange(1501, 2000)//从1501-2000.addUnboundedFrom(2001);//2000到正无穷
// 获得我们设置的聚合Range agg = response.getAggregations().get("rang_price");// 循环数据输出for (Range.Bucket entry : agg.getBuckets()) {Map<String, Object> map = new HashMap<String, Object>();// 处理String key = entry.getKeyAsString(); // Range as key Number from = (Number) entry.getFrom(); // Bucket from Number to = (Number) entry.getTo(); // Bucket to long docCount = entry.getDocCount(); // Doc count// 封装map.put("key", key);map.put("doc_count", docCount);System.out.println(map);}3.2.Date Range Aggregation日期范围
AggregationBuilder aggregation = AggregationBuilders .dateRange("agg") .field("dateOfBirth")//field名称 .format("yyyy")//日期格式 .addUnboundedTo("1950") // from -infinity to 1950 (excluded) .addRange("1950", "1960") // from 1950 to 1960 (excluded) .addUnboundedFrom("1960"); // from 1960 to +infinity
for (Range.Bucket entry : agg.getBuckets()) { String key = entry.getKeyAsString(); // Date range as key DateTime fromAsDate = (DateTime) entry.getFrom(); // Date bucket from as a Date DateTime toAsDate = (DateTime) entry.getTo(); // Date bucket to as a Date long docCount = entry.getDocCount(); // Doc count}
3.3 IP Range Aggregation ip范围分组
IpRangeAggregationBuilder aggregation1 = AggregationBuilders .ipRange("agg") .field("ip") .addUnboundedTo("192.168.1.0") // 从负无穷到192.168.1.0 .addRange("192.168.1.0", "192.168.2.0") // 从 192.168.1.0 到 192.168.2.0 (excluded) .addUnboundedFrom("192.168.2.0"); // 从 192.168.2.0 到 +infinity
for (Range.Bucket entry : aggregation1.getBuckets()) { String key = entry.getKeyAsString(); // Ip 范围 as key String fromAsString = entry.getFromAsString(); // Ip bucket from as a String String toAsString = entry.getToAsString(); // Ip bucket to as a String long docCount = entry.getDocCount(); // Doc count}4. Filters Aggregation 过滤分组:根据过滤条件进行分组
AggregationBuilder aggregation = AggregationBuilders .filters("agg", new FiltersAggregator.KeyedFilter("men", QueryBuilders.termQuery("gender", "male")), new FiltersAggregator.KeyedFilter("women", QueryBuilders.termQuery("gender", "female")));
// For each entryfor (Filters.Bucket entry : agg.getBuckets()) { String key = entry.getKeyAsString(); // bucket key long docCount = entry.getDocCount(); // Doc count logger.info("key [{}], doc_count [{}]", key, docCount);}
key [men], doc_count [4982]key [women], doc_count [5018]
三、Metrics aggregations 聚合分析的使用
官方参考文档:
https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/_metrics_aggregations.html
3.1常用的:Avg,Max,Sum等等
我通过一个需求将metric的javaAPI进行说明,需求是:查询电视销售每个颜色的平均价格、最高价格、总价格并按照平均价格降序排序,对应的sql语句为:
select avg(price) avg_price,max(price) max_price,sum(price) sum_price from tvs.sales group by color order by avg_price
/** * 查询电视销售每个颜色的平均价格、最高价格、总价格并按照平均价格降序排序* @Title: metrics * @Description: TODO(这里用一句话描述这个方法的作用) * @param @throws UnknownHostException* @return void* @autor lpl* @date 2017年11月6日* @throws */@Testpublic void metrics() throws UnknownHostException{// 创建查询索引和typeSearchRequestBuilder srBuilder =EsClient.client().prepareSearch("tvs").setTypes("sales");// colorAggs// 如果需要进行排序的话,可以使用order(Order.aggregation("avg_price",true))// "avg_price"对应下班的字聚合的名称,true表示升序排序。false表示倒叙排序TermsAggregationBuilder colorsAgg = AggregationBuilders.terms("colors").field("color").order(Order.aggregation("avg_price", true));// 平均值AvgAggregationBuilder avgAgg = AggregationBuilders.avg("avg_price").field("price");// 最大值aMaxAggregationBuilder maxAgg = AggregationBuilders.max("max_price").field("price");// 总和SumAggregationBuilder sumAgg = AggregationBuilders.sum("sum_price").field("price");SearchResponse response = srBuilder.setSize(0).addAggregation(colorsAgg.subAggregation(avgAgg).subAggregation(maxAgg).subAggregation(sumAgg)).execute().actionGet();Terms terms = response.getAggregations().get("colors");//处理结果for (Terms.Bucket entry : terms.getBuckets()) {Map<String, Object> map = new HashMap<String, Object>();// 获得按照颜色进行分组的桶String keyAsString = entry.getKeyAsString();// 获得每个分组的数量long docCount = entry.getDocCount();// 获得平均价格Avg avg = entry.getAggregations().get("avg_price");// 获得最大价格Max max = entry.getAggregations().get("max_price");// 获得价格总和Sum sum = entry.getAggregations().get("sum_price");map.put("key", keyAsString);map.put("docCount", docCount);map.put("avg", avg.getValue());map.put("max", max.getValue());map.put("sum", sum.getValue());System.out.println(map);}}3.2 Percentile Aggregation百分比聚合分析
PercentilesAggregationBuilder aggregation = AggregationBuilders .percentiles("agg") .field("height") .percentiles(1.0, 5.0, 10.0, 20.0, 30.0, 75.0, 95.0, 99.0);
// sr is here your SearchResponse objectPercentiles agg = response.getAggregations().get("agg");// For each entryfor (Percentile entry : agg) { double percent = entry.getPercent(); // Percent double value = entry.getValue(); // Value}
percent [1.0], value [0.814338896154595]percent [5.0], value [0.8761912455821302]percent [25.0], value [1.173346540141847]percent [50.0], value [1.5432023318692198]percent [75.0], value [1.923915462033674]percent [95.0], value [2.2273644908535335]percent [99.0], value [2.284989339108279]
上边就是我对elasticsearch的聚合分析的一些javaAPI使用的总结,当然我只写出了一部分,强大的elasticsearch还有很多的接口,大家可以通过上边我提供的连接进入elasticsearch的官网进行查询。在前面的文章中我也对elasticsearch的常用搜索、curd、高亮显示、搜索建议进行了记录,如果大家有兴趣可以去翻阅。文章中有哪些地方有误请大家及时指出,感激不尽,相互交流,共同进步!
- javaAPI实现elasticsearch5.5.2的聚合分析
- JavaAPI实现Elasticsearch5.5.2一些常用的搜索
- elasticsearch5.5.2用javaAPI实现搜索结果高亮显示和搜索建议
- Elasticsearch5.X聚合简介
- ElasticSearch5.X搜索条件的聚合(六)
- ElasticSearch5.X尝试聚合(一)
- elasticsearch5.x的java实现搜索
- Elasticsearch5和head最新插件学习,JavaAPI demo
- 聚合实现的示意图
- COM聚合的实现
- COM聚合的实现
- com 聚合的实现
- Elasticsearch5.2.2进行数据聚合测试
- Elasticsearch5.3 JAVA Demo 聚合查询
- ElasticSearch5.X添加度量聚合(二)
- ElasticSearch5.X聚合-条形图(四)
- ElasticSearch5.X按时间统计-聚合
- mongodb的sum操作以及javaapi的实现
- 洛谷 P3941 入阵曲
- 连续总结第二十五天
- Android通过音量键调节音量大小
- 计算机基础-嵌入式CPU选型
- Java中的异常处理
- javaAPI实现elasticsearch5.5.2的聚合分析
- K60学习 KEA学习
- 【技术】--swagger
- 视觉slam14讲——第7讲 视觉里程计1
- [2017纪中11-5]好路线 DP
- matlab 函数集锦
- 20171105在杭州
- 【代码优化】学会利用“配置文件”优化我们的代码结构
- 微积分