需要实现以下SQL产生的效果
select date_format(create_time, '%Y-%m-%d') as date,
count(class_id) as num
from news_info where create_time between #{start_time}
and #{end_time}
group by date;
不带日期范围搜索条件
select date_format(create_time, '%y-%m-%d') as date,
count(class_id) as num
from news_info
group by date;
带日期范围搜索条件
select date_format(create_time, '%y-%m-%d') as date,
count(class_id) as num
from news_info
where create_time between '2021-08-25' and '2021-09-15'
group by date;
跟随SpringBoot依赖版本,<spring-boot.version>2.6.4</spring-boot.version>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
public void testAggs() throws IOException {
//构建搜索请求
SearchRequest searchRequest = new SearchRequest("news_info");
//构建日期直方图聚合生成器
DateHistogramAggregationBuilder dateHistogramAggregationBuilder =
AggregationBuilders
//自定义名称
.dateHistogram("1天间隔")
//分组字段
.field("create_time")
//日期格式
.format(EsConstants.YYYY_MM_DD);
//dateHistogramInterval(),这个方法已经过时,推荐使用dateHistogramAggregationBuilder.fixedInterval()
dateHistogramAggregationBuilder
//间隔:1天
.fixedInterval(DateHistogramInterval.days(1))
//最小返回0
.minDocCount(0);
//构造搜索源生成器,配置聚合生成器
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder().aggregation(dateHistogramAggregationBuilder);
//配置搜索源生成器
searchRequest.source(sourceBuilder);
//使用RestHighLevelClient搜索
SearchResponse search = client.search(searchRequest, RequestOptions.DEFAULT);
//根据自定义名称获取直方图
Histogram histogram = search.getAggregations().get("1天间隔");
//遍历获取数据
List<? extends Histogram.Bucket> buckets = histogram.getBuckets();
for (Histogram.Bucket bucket : buckets) {
System.out.println("date:" + bucket.getKeyAsString() + " ---> " + " num:" + bucket.getDocCount());
}
}
[示例图]
… 中间省略(输出内容太多,只截取开头与结尾)
使用demo,的确是可以查询出所有的分组数据,不存在的日期也可以补0输出,但是我想自己控制查询日期的范围,好像无法做到。
于是,百度 + 查询官网,发现有个dateHistogramAggregationBuilder.extendedBounds()
方法可以设置查询日期的范围。
dateHistogramAggregationBuilder
//间隔:1天
.fixedInterval(DateHistogramInterval.days(1))
//最小返回0
.minDocCount(0)
.timeZone(ZoneId.systemDefault())
//扩展边界
.extendedBounds(new LongBounds("2021-08-25","2021-09-15"))
;
前部分:
后部分:
与[示例图2]
一样,一直输出到2022-05-17。
按照date分组查询统计对应的数值
查询从开始日期开始~数据库中最后一个分组有值的日期
输出到最后一个分组统计(num)有值的日期截止。
dateHistogramAggregationBuilder
//间隔:1天
.fixedInterval(DateHistogramInterval.days(1))
//最小返回0
.minDocCount(0)
.timeZone(ZoneId.systemDefault())
//硬边界
.hardBounds(new LongBounds("2021-08-25","2021-09-15"))
;
按照date分组查询统计对应的数值
查询从开始日期~截止日期的范围
输出该范围内最后一个分组统计(num)有值的日期截止。
public void testAggs() throws IOException {
//构建搜索请求
SearchRequest searchRequest = new SearchRequest("news_info");
//构建日期直方图聚合生成器
DateHistogramAggregationBuilder dateHistogramAggregationBuilder =
AggregationBuilders
//自定义名称
.dateHistogram("1天间隔")
//分组字段
.field("create_time")
//日期格式
.format(EsConstants.YYYY_MM_DD);
//dateHistogramInterval(),这个方法已经过时,推荐使用dateHistogramAggregationBuilder.fixedInterval()
dateHistogramAggregationBuilder
//间隔:1天
.fixedInterval(DateHistogramInterval.days(1))
//最小返回0
.minDocCount(0)
//时区
.timeZone(ZoneId.systemDefault())
//硬边界
.hardBounds(new LongBounds("2021-08-25","2021-09-15"))
//扩展边界
.extendedBounds(new LongBounds("2021-08-25","2021-09-15"));
//构造搜索源生成器,配置聚合生成器
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder().aggregation(dateHistogramAggregationBuilder);
//配置搜索源生成器
searchRequest.source(sourceBuilder);
//使用RestHighLevelClient搜索
SearchResponse search = client.search(searchRequest, RequestOptions.DEFAULT);
//根据自定义名称获取直方图
Histogram histogram = search.getAggregations().get("1天间隔");
//遍历获取数据
List<? extends Histogram.Bucket> buckets = histogram.getBuckets();
for (Histogram.Bucket bucket : buckets) {
System.out.println("date:" + bucket.getKeyAsString() + " ---> " + " num:" + bucket.getDocCount());
}
}
按照date分组查询统计对应的数值
**查询从开始日期~**截止日期的范围
输出该范围内所有日期,无值的补0。
额外话:其实直接获取全部的数据也是可以做到需求所要的效果:反正es查询性能很强大,可以直接查询全部数据,然后通过Java8的Stream的filter来进行日期范围条件过滤。
由于昨天的测试数据有问题,导致描述不准确,以下是今天的测试结果:
首先一点:扩展边界必须在硬边界内(两个边界的startTimeendTime可以相同,如果设置不同,那么扩展边界的startTimeendTime,必须在硬边界的startTime~endTime范围之间)
dateHistogramAggregationBuilder
//硬边界
.hardBounds(new LongBounds("2022-08-07", "2022-08-10"))
//扩展边界
.extendedBounds(new LongBounds("2022-08-07", "2022-08-10"))
dateHistogramAggregationBuilder
//硬边界
.hardBounds(new LongBounds("2022-08-07", "2022-08-10"))
//扩展边界
.extendedBounds(new LongBounds("2022-08-08", "2022-08-10"))
dateHistogramAggregationBuilder
//硬边界
.hardBounds(new LongBounds("2022-08-07", "2022-08-10"))
//扩展边界
.extendedBounds(new LongBounds("2022-08-08", "2022-08-09"))
不论endTime = 2022-08-09,2022-08-08,2022-08-07,结果3都是一样的。
报错:重点就是**“reason”:“Extended bounds have to be inside hard bounds”**
{“error”:{“root_cause”:[{“type”:“illegal_argument_exception”,“reason”:“Extended bounds have to be inside hard bounds, hard bounds: [2022-08-08–2022-08-10], extended bounds: [2022-08-07–2022-08-09]”}],“type”:“search_phase_execution_exception”,“reason”:“all shards failed”,“phase”:“query”,“grouped”:true,“failed_shards”:[{“shard”:0,“index”:“im_message”,“node”:“_13QIC8wRO2prdBPFLE0DA”,“reason”:{“type”:“illegal_argument_exception”,“reason”:“Extended bounds have to be inside hard bounds, hard bounds: [2022-08-08–2022-08-10], extended bounds: [2022-08-07–2022-08-09]”}}],“caused_by”:{“type”:“illegal_argument_exception”,“reason”:“Extended bounds have to be inside hard bounds, hard bounds: [2022-08-08–2022-08-10], extended bounds: [2022-08-07–2022-08-09]”,“caused_by”:{“type”:“illegal_argument_exception”,“reason”:“Extended bounds have to be inside hard bounds, hard bounds: [2022-08-08–2022-08-10], extended bounds: [2022-08-07–2022-08-09]”}}},“status”:400}
感谢IT界的eason哥帮我找到了官网链接:(我其实找到过这个地方,但是细心看所以错过了,害,下次注意) 直方图文档介绍