前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java 通过RestHighLevelClient 使用ES的date_histogram 根据年月日做统计

Java 通过RestHighLevelClient 使用ES的date_histogram 根据年月日做统计

作者头像
heasy3
发布2020-08-02 22:03:38
3.7K0
发布2020-08-02 22:03:38
举报

只写了后台,前端请求带上dateType给后台,后端返回封装了json字符串的map

GsonUtil.getJsonStringByObject()是封装的Gson.toJson的方法

前端接受解析结果 并设置echatrs参数 即可完成图表绘制

代码语言:javascript
复制
/**
 * 消息趋势统计 dateType由前端传递 包括年月周
 * 按年则统计过去12个月
 * 按月则统计过去30天
 * 按周则统计过去7天
**/
public Map<String, String> msgTrendCount(String dateType) {
    //每个索引的时间field name 可能不同 根据索引设置
	String rangeField = "messageSendTime";
    //索引名
	String index = EsIndexName.TG_MESSAGE.getIndexName();
	return dateHistogram(rangeField, dateType, index);
}




private Map<String, String> dateHistogram(String rangeField, String dateType, String... indices) {
	Map<String, String> map = new HashMap<>(4);
	try {

		LocalDateTime now = LocalDateTime.now();
		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
		String from;
		//extended bounds参数
		String boundsStart;
		String boundsEnd;
		String to = formatter.format(now);
		String format = "yyyy-MM-dd";
		//bounds的格式化类型需要和format相同
		DateTimeFormatter boundsFormatter = DateTimeFormatter.ofPattern(format);
		//间隔 年类型较为特殊
		DateHistogramInterval interval = DateHistogramInterval.DAY;
		switch (dateType) {
			case "week": {
				from = formatter.format(now.minusDays(6));
				boundsStart = boundsFormatter.format(now.minusDays(6));
				boundsEnd = boundsFormatter.format(now);
				break;
			}
			case "year": {
				from = formatter.format(now.minusMonths(11));
				format = "yyyy-MM";
				boundsFormatter = DateTimeFormatter.ofPattern(format);
				interval = DateHistogramInterval.MONTH;
				boundsStart = boundsFormatter.format(now.minusMonths(11));
				boundsEnd = boundsFormatter.format(now);
				break;
			}
			case "month":
			default: {
				from = formatter.format(now.minusDays(29));
				boundsStart = boundsFormatter.format(now.minusDays(29));
				boundsEnd = boundsFormatter.format(now);
				break;
			}
		}

		//范围查询
		BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
		boolQueryBuilder.must(QueryBuilders.rangeQuery(rangeField).from(from).to(to));
		//dateHistogram
		AggregationBuilder aggregationBuilder = AggregationBuilders.dateHistogram("dateHistogram")//自定义名称
				.dateHistogramInterval(interval)//设置间隔
				.minDocCount(0)//返回空桶
				.field(rangeField)//指定时间字段
				.format(format)//设定返回格式
				.extendedBounds(new ExtendedBounds(boundsStart, boundsEnd));//设定范围

		SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
		//指定size为0 不返回文档 因为只需要数量
		searchSourceBuilder.query(boolQueryBuilder).aggregation(aggregationBuilder).size(0);

		SearchRequest searchRequest = new SearchRequest();
		searchRequest.source(searchSourceBuilder);
		searchRequest.indices(indices);
		SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
		Aggregation agg = searchResponse.getAggregations().get("dateHistogram");

		List<? extends Histogram.Bucket> buckets = ((Histogram) agg).getBuckets();
		List<String> dateList = new ArrayList<>(30);
		List<String> countList = new ArrayList<>(30);
		for (Histogram.Bucket bucket : buckets) {
			// maybe:如果不是年 则将key中的年份去掉
			dateList.add(bucket.getKeyAsString());
			countList.add(String.valueOf(bucket.getDocCount()));
		}
		map.put("chartTime", GsonUtil.getJsonStringByObject(dateList));
		map.put("chartCount", GsonUtil.getJsonStringByObject(countList));
	} catch (Exception e) {
		log.error("统计日期直方图出错:" + e.getMessage());
	}
	return map;
}

之前费劲写的好多代码来做这个统计,分别用日期去一天天的查数量,最近学习了解了es自带的 date_histogram

完全契合需求,遂将原笨拙的代码删除改为es的自带聚合 (果然人还是要多读书呀。。。)

速度上目前文档数量不大,没有差别,但预计随着后期文档数量增加,肯定是es的聚合更加高效。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-03-07 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档