elasticsearch时间柱状图聚合java实现

需求:统计每天有多少条数据,以及某字段的平均值。

1. 使用DateHistogramAggregationBuilder按天统计,再嵌入aggs取平均值。

如果要对结果进行排序,在 AggregationBuilders 加上 .order(Histogram.Order.COUNT_DESC)

1
2
3
4
5
6
7
8
9
10
11
AvgAggregationBuilder avgAggregationBuilder = AggregationBuilders
.avg("avg_aggsName")
.field("fieldName");
DateHistogramAggregationBuilder dateHistogramAggregationBuilder = AggregationBuilders
.dateHistogram("aggsName")
.field("fieldName") //可以是time
.dateHistogramInterval(DateHistogramInterval.DAY)
.format("yyyy-MM-dd")
.minDocCount(0L)
.subAggregation(avgAggregationBuilder);
2. 如果再新增一条需求:只统计近一个月的数据。

那么就加一条filter,过滤后再聚合。

1
2
3
4
5
6
7
8
9
10
11
12
//日期限制
QueryBuilder rangeBuilder = QueryBuilders
.rangeQuery(aggsName)
.format("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
.gte(timeRange.get("startTime").toString())
.lte(timeRange.get("endTime").toString());
// 过滤后聚合 .missing(0)
QueryBuilder queryBuilder = QueryBuilders
.boolQuery()
.filter(rangeBuilder);
3. 获取当天/一周内/一个月内起始时间
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
private static Map<String, String> getTime(String period) {
Map<String, String> timeRange = new HashMap<>();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
Calendar calendar = Calendar.getInstance();
timeRange.put("endTime", simpleDateFormat.format(calendar.getTime()));
switch (period) {
case "week": {
calendar.add(Calendar.DATE, -7);
}
break;
case "month": {
calendar.add(Calendar.MONTH, -1);
}
break;
default: break;
}
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
timeRange.put("startTime", simpleDateFormat.format(calendar.getTime()));
return timeRange;
}
4. 整合查询语句
1
2
3
4
5
searchSourceBuilder
.query(queryBuilder)
.aggregation(dateHistogramAggregationBuilder);
String query = searchSourceBuilder.toString();

需求:获取type/index下最新一条记录

首先用 matchAll 匹配所有数据,再根据时间排序。最终获取 getFirstHit,得到最新记录。(字段中最好包含time字段)

1
2
3
4
5
6
QueryBuilder queryBuilder = QueryBuilders
.matchAllQuery();
searchSourceBuilder
.query(queryBuilder)
.sort("time", SortOrder.DESC);

输出结果

1. 获取 hits 数据:
1
2
3
4
5
List<SearchResult.Hit<TESTCLASS, Void>> hits = result.getHits(TESTCLASS.class);
List<TESTCLASS> userList = new ArrayList<>();
for (SearchResult.Hit<TESTCLASS, Void> hit : hits) {
userList.add(hit.source);
}
2. 获取 aggs 里的 buckets 数据:
1
MetricAggregation jsonAggs = searchResult.getAggregations();

日期柱状图

1
2
3
4
5
Map<String,Object> map = new HashMap<>();
DateHistogramAggregation histogram = jsonAggs.getDateHistogramAggregation("aggsName");
for (DateHistogramAggregation.DateHistogram entry : histogram.getBuckets()) {
map.put(entry.getTimeAsString(), entry.getCount());
}

求平均值

1
2
AvgAggregation avg = jsonAggs.getAvgAggregation("avg_aggsName");
result.put("avg_aggsName", Math.ceil(avg.getAvg()));