1. date_histogram使用
跟histogram类似,按时间区间分割数据。
{
"query": {
"bool": {
"must": [{
"range": {
"@timestamp": {
"gte": 1573113999000,
"lte": 1573114599000
}
}
}]
}
},
// 不显示_source
"size": 0,
"aggs": {
"dateHistogramAgg": {
"date_histogram": {
// 分组的字段
"field": "timestamp_mills",
// 聚合区间
"interval": "5s",
// 设置时区, 东八区
// "time_zone":"+08:00",
// 返回KEY格式化显示
"format": "yyyy-MM-dd HH:mm:ss",
// 最小文档数,为0的桶也显示,默认不显示
"min_doc_count": 0,
// 设置时间范围,默认只返回文档中有的最小时间,最大时间之间的桶
"extended_bounds": {
"min": 1573113999000,
"max": 1573114599000
}
}
}
}
}
说明
min_doc_count: 设置返回桶的最小文档数,设置为0表示没有文档也返回该桶,默认不会返回空bucket。
extended_bounds: 设置返回桶的时间范围,Elasticsearch 默认只返回你的数据中最小值和最大值之间的 buckets。
2 坑
2.1 date_histogram返回的桶前后时间会有偏差
我的查询返回时1573113999000到1573114599000,也就是2019-11-07 16:06:39到2019-11-07 16:16:39,以10s分割,但是返回的第一个桶的时间是2019-11-07 16:06:30,已经超过了我 extended_bounds设置的时间。
至于偏差多少时间,跟interval有关,设置1s就不会偏差
原因:
es内部计算桶的时间跟我们理解的不一样,不是开始时间 + interval。
计算es桶聚合bucket_key的公式是 bucket_key = Math.floor((value - offset) / interval) * interval + offset
根据公式console.log(Math.floor((1573113999000 - 0) / 10000) * 10000 + 0)
结果是1573113990000,也就是2019-11-07 16:06:30
2.2 date_histogram第一个桶的数据不准确
因为我得业务是取钱10分钟的数据,以10s分割,折线图显示。但是运行发现,第一个桶返回的数值越来越小。
原因:
还是与es内部计算桶方式有关,如果es返回的桶前后时间会有偏差的话,那么第一个桶的数据也会有偏差,每次刷新虽然第一个桶的key不变,但是内部实际查询的时间区间会越来越短,所以导致第一个桶的数据越来越小。
我的解决办法是把第一桶删掉。
以上是我的猜想