专栏首页用户7614879的专栏Java 通过RestHighLevelClient 使用ES的date_histogram 根据年月日做统计

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

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

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

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

/**
 * 消息趋势统计 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的聚合更加高效。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • ES Pipeline Aggregation(管道聚合)

    同级管道聚合,它计算同级聚合中指定度量的平均值。同级聚合必须是多桶聚合,针对的是度量聚合(metric Aggregation)。 示例如下:

    丁威
  • elasticsearch使用指南之桶聚合(Bucket)上篇

    Buket Aggregations(桶聚合)不像metrics Aggregations(度量聚合)那样计算字段上的度量,而是创建文档桶,每个文件桶有效地定义...

    丁威
  • 万字长文:详解 Spring Boot 中操作 ElasticSearch

    ElasticSearch 是一个基于 Lucene 的搜索服务器。它提供了一个分布式多员工能力的全文搜索引擎,基于 RESTful web 接口。Elasti...

    程序员小强
  • ES系列16:管道聚合你都不会?那你如何做聚合分析

    学习管道聚合,是为了完成更复杂的聚合分析,通过本文,你将对管道聚合的各种类型的功用和使用场景有一个全面的掌握。当遇到聚合需求时,可以快速反应,选用合适的聚合类型...

    方才编程_公众号同名
  • ES的常用查询与聚合

    基于es 5.4和es 5.6,列举的是个人工作中经常用到的查询(只是工作中使用的是Java API),如果需要看完整的,可以参考官方相关文档 https://...

    阿泽
  • ElasticSearch 桶聚合

    松哥原创的 Spring Boot 视频教程已经杀青,感兴趣的小伙伴戳这里-->Spring Boot+Vue+微人事视频教程

    江南一点雨
  • Elasticsearch聚合学习之二:区间聚合

    版权声明:欢迎转载,请注明出处,谢谢。 https://blog.csdn.net/boling_cavalry/article/detail...

    程序员欣宸
  • 应用接入ES(一)-Springboot集成ES

    Elasticsearch 是一个分布式的开源搜索和分析引擎,适用于所有类型的数据,包括文本、数字、地理空间、结构化和非结构化数据。Elasticsearch ...

    叔牙
  • Elasticsearch:Java 运用示例

    在今天的文章中,我们来介绍如何使用 Java 来访问 Elasticsearch。

    腾讯云大数据
  • Spring Boot(三)集成ElasticSearch

    ELK是Elasticsearch、Logstash、Kibana三大开源框架首字母大写简称。市面上也被成为Elastic Stack。其中Elasticsea...

    HcodeBlogger
  • Elasticsearch:pipeline aggregation 介绍

    所有的这些问题,我们都可以使用 Pipeline aggregation 来算出来,这是因为这些数据的统计需要用到它的 parent 或 sibling 级的聚...

    腾讯云大数据
  • springboot实战之nosql整合(elasticsearch7.3版本)

    在正文之前,我先感慨下,elasticsearch版本更新实在是太快了。2019年4月时候,我看到的版本还是7.0版本,现在9月,已经出到了7.3版本了,而且7...

    lyb-geek
  • ElasticSearch

    ​ 把句子划分为关键字,会把数据库中数据分词后匹配,ik_smart最少切分,ik_max_word最细粒度切分

    Dean0731
  • 彻底搞懂 Elasticsearch Java API

    在明确了ES的基本概念和使用方法后,我们来学习如何使用ES的Java API. 本文假设你已经对ES的基本概念已经有了一个比较全面的认识。

    小勇DW3
  • Elasticsearch-Java

    直接使用 HTTP 请求,去操作 Es。HTTP 请求工具,可以使用 Java 自带的 HttpUrlConnection,也可以使用一些 HTTP 请求库,例...

    乐心湖
  • ElasticSearch高版本API的使用姿势

    ElasticSearch之前我没有深入去学过,在上家公司也是简单用了一下,本来是想用来做千万级ip库数据缓存的,后面查询耗时就弃用了,也就没有深入去学习。之前...

    Bug开发工程师
  • 触类旁通Elasticsearch:聚合

    熟悉SQL的用户一定对聚合不会陌生,简单说任何应用于group by的查询都会执行一个聚合操作。ES的聚合(aggregation)加载和搜索相...

    用户1148526
  • 使用elasticsearch搭建自己的搜索系统

    ?es搜索系统封装源码,走过路过,请帮我点个star哦! ?原文地址为https://www.cnblogs.com/haixiang/p/12451703....

    海向
  • 微服务[学成在线] day10:课程发布、ElasticSearch

    课程发布后将生成正式的课程详情页面,课程发布后用户即可浏览课程详情页面,并开始课程的学习。课程发布生成课程详情页面的流程与课程预览业务流程相同,如下:

    LCyee

扫码关注云+社区

领取腾讯云代金券