最近有个需求,前端传入时间间隔,去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;}