最近有个需求,前端传入时间间隔,去elasticsearch按照时间间隔统计每个时间间隔内数据量。
public List<HashMap<String,Object>> getCount(@RequestParam Integer time, @RequestParam String selectedDatedTime) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
format.setTimeZone(TimeZone.getTimeZone(ZoneId.of(DateUtil.TIMEZONE_ZONE_ID)));
Date date = CommonUtil.getDateByString(selectedDatedTime);
Calendar fromDate = Calendar.getInstance();
fromDate.setTime(date);
fromDate.add(Calendar.HOUR_OF_DAY, -time);
Calendar toDate = Calendar.getInstance();
toDate.setTime(date);
RangeQueryBuilder timeRangeQuery = QueryBuilders.rangeQuery(ApplicationConstant.TIMESTAMP)
// .timeZone("Asia/Singapore")
.gte(fromDate.getTimeInMillis())
.lt(toDate.getTimeInMillis());
String application = "";
if (applications != null && applications.size() > 0){
application = applications.get(0);
}
IndexCoordinates index = IndexCoordinates.of("xxxxxxx");
DateHistogramInterval timeInterval = null;
if(time==1){
timeInterval= DateHistogramInterval.minutes(5);
}else if(time==24 || time==6 ||time==12){
timeInterval = DateHistogramInterval.hours(1);
}else{
timeInterval= DateHistogramInterval.hours(12);
}
Query sq = new NativeSearchQueryBuilder()
.withQuery(timeRangeQuery)
.addAggregation(AggregationBuilders.dateHistogram("date_histogram")
.field(TIMESTAMP_FIELD_NAME)
.fixedInterval(timeInterval)
.minDocCount(0)
.timeZone(ZoneId.of(DateUtil.TIMEZONE_ZONE_ID))
.extendedBounds(new ExtendedBounds(fromDate.getTimeInMillis(), toDate.getTimeInMillis()))
)
.withPageable(Pageable.unpaged())
.build();
return esservice.getCountApi(sq, index);
}
这里面的 timeInterval 就是设定间隔时间。
加入 extendedBounds 目的就是防止出现0数据不会返回,例如我只有8am到12am内有数据,现在是12am,timeInterval是一小时,总共时间跨度是12小时。如果不设置extendedBounds的话,date_histogram查询出来的聚合只会有8am-9am,9am-10am,10am-11am,11am-12am这几个的聚合,不会有8am之前的聚合出现,照理来说,会出现12个聚合,不管有没有数据都有聚合返回,只不过某些聚合出来docCount是0而已。所以需要加上这个条件
因为前端ui需要进行展示,就算没有数据也需要展示。例如这个chart的前半段,虽然聚合出来没有数据,但是也需要展示0数据。
这边是处理数据的service
public List<HashMap<String, Object>> getCountApi(Query sq, IndexCoordinates esindex) {
HashMap<String, Object> data = new HashMap<>();
List<HashMap<String, Object>> list = new ArrayList<>();
SearchHits<HashMap> result = template.search(sq, HashMap.class, esindex);
Aggregations agg = result.getAggregations();
if (agg != null) {
ParsedDateHistogram histogram = agg.get("date_histogram");
List<HashMap<String, Object>> innerlist = new ArrayList<>();
for (Histogram.Bucket timebucket : histogram.getBuckets()) {
HashMap<String, Object> tempMap = new HashMap<>();
ZonedDateTime zdt = (ZonedDateTime) timebucket.getKey();
DateTime dt = new DateTime(zdt.toEpochSecond() * 1000L, DateTimeZone.forID(DateUtil.TIMEZONE_ZONE_ID));
// String dateStr = dt.toString("yyyy-MM-dd HH:mm:ss");
tempMap.put("x", dt.getMillis());
tempMap.put("y", timebucket.getDocCount());
innerlist.add(tempMap);
}
data.put("data", innerlist);
data.put("name", NAME_OF_TYPE);
list.add(data);
}
return list;
}