ES中对于时间聚合的一些总结
最近在通过es统计数据时,遇到了一个问题:在进行时间范围查询后,再对时间进行聚合,此时聚合的结果会受时区影响,也就是说结果的时间戳会被转换成对应时区的时间,并且时间戳也会变成这个时间的时间戳,所以就会导致结果的时间以及时间戳和查询的时间范围不匹配。
以下是demo演示:
首先向索引中添加数据,时间字段是alarmTime,时间跨度从8月1号到9月1号
并且在8月27号新增了两条数据
现在对8.27到9.1按照每天统计数据量
进行查询
curl --location --request GET 'http://localhost:9200/tlp_alarm_demo/_search' \
--header 'User-Agent: Apifox/1.0.0 (https://apifox.com)' \
--header 'Content-Type: application/json' \
--data-raw '{
"timeout": "15000ms",
"size": "0",
"query": {
"bool": {
"filter": [
{
"terms": {
"ordId": [
"1826497452249849856"
]
}
},
{
"range": {
"alarmTime": {
"gte": "1724688000000",
"lte": "1725206357000"
}
}
}
],
"adjust_pure_negative": true
}
},
"aggregations": {
"x": {
"date_histogram": {
"field": "alarmTime",
"format": "yyyy-MM-dd",
"calendar_interval": "1d",
"offset": 0,
"order": {
"_key": "asc"
},
"keyed": false,
"min_doc_count": 0
}
}
}
}'
聚合结果为:
可以发现返回的结果是从8.26开始了,并且doc_count变成了2
通过查阅官方文档可以发现:
- 当我们在 Elasticsearch 中进行时间范围查询,然后再对这些时间进行聚合时,时区会影响结果的表示。Elasticsearch 在聚合时会根据指定的时区来处理时间段(默认为UTC),这就会会导致结果时间戳与查询的时间范围不匹配。
ES中的时区
- Elasticsearch 默认使用 UTC 时间存储和处理时间字段。
- 需要将时间数据按照特定时区进行存储、查询和聚合,以满足业务需求。
- 我国属于东八区时间,是比 UTC 时间快 8 小时的时区,所以要让结果正确的显式,就需要指定时区参数
通过官方文档可以发现,在 Elasticsearch 中,参数offset 和 time_zone 都与时间处理有关,总结下来就是:
time_zone
用于指定时间字段在聚合时应使用的时区。它影响的是日期聚合的分桶方式和结果的显示。例如,如果你想按照东八区时间进行每天的聚合,而不是默认的 UTC 时间。
offset
用于在聚合时对分桶的时间进行偏移。它不改变时区,而是直接在时间轴上对分桶进行偏移。例如,如果你想让每天的分桶从上午 8 点开始而不是午夜 0 点开始,通俗的说就是,es中的按天统计是从第一天的00:00到第二天的00:00,如果希望是从第一天的08:00到第二天的08:00统计,那么就需要用offset来进行偏移。
不难发现在上述的例子中,需要使用time_zone指定时区就可以正确返回
"aggregations": {
"x": {
"date_histogram": {
"field": "alarmTime",
"format": "yyyy-MM-dd",
"calendar_interval": "1d",
"offset": 0,
"order": {
"_key": "asc"
},
"keyed": false,
"time_zone": "+08:00",
"min_doc_count": 0
}
}
}
响应数据正确
#总结
- 在ES中,对于时间字段,最好使用多字段类型,而不是单一的long字段(由于 long 类型的时间戳不包含时区信息,Elasticsearch 可能在聚合或展示时间时,将这些时间戳按照默认的 UTC 时区解释并显示,导致时间范围出现不匹配)
- 官方文档给出的时间类型定义方式
"alarmTime": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
}
- 在 date_histogram 聚合中明确指定时区,以避免聚合结果与查询时间范围不匹配的问题。