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 聚合中明确指定时区,以避免聚合结果与查询时间范围不匹配的问题。
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值