date_histogram 是什么
date_histogram 聚合按时间区间分桶统计:calendar_interval 按日历单位分(minute/hour/day/week/month/quarter/year),fixed_interval 按固定时长分(30s/5m/2h/7d)。日历单位与时区相关,固定时长与日历无关,两者不能同时使用。它是做趋势图、按天汇总与时间序列看板的核心聚合,常与 terms 或指标聚合嵌套使用。
基本信息
| 日历间隔 | calendar_interval:day / week / month / quarter / year |
|---|---|
| 固定间隔 | fixed_interval:30s / 5m / 2h / 7d,不能与日历单位混用 |
| 常用参数 | time_zone、min_doc_count、extended_bounds、format、offset |
| 返回内容 | 每个桶含 key(毫秒时间戳)、key_as_string、doc_count |
| 嵌套用法 | 桶内可再挂 terms 或指标子聚合 |
| 适用版本 | Elasticsearch 7.x / 8.x |
典型使用场景
- 按天统计活跃用户或订单量,画趋势折线
- 按小时看接口调用量,定位流量高峰时段
- 按周或按月出运营报表,口径与时区对齐
- 桶内再按状态分组,观察各类占比变化
- 统计日志错误率的时间分布,定位故障时段
- 用 extended_bounds 补全空白区间让时间轴连续
示例
示例
GET /logs/_search
{
"size": 0,
"query": { "range": { "@timestamp": { "gte": "now-7d/d", "lt": "now/d" } } }, # 只统计近 7 天
"aggs": {
"per_day": {
"date_histogram": {
"field": "@timestamp",
"calendar_interval": "day",
"time_zone": "+08:00", # 按东八区分天
"min_doc_count": 0, # 保留空桶
"extended_bounds": { "min": "now-7d/d", "max": "now/d" },
"format": "yyyy-MM-dd",
"aggs": { "by_status": { "terms": { "field": "status" } } }
}
}
}
}关键参数读法
| 参数 | 作用 | 注意点 |
|---|---|---|
| calendar_interval | 按日历单位分桶 | 与 time_zone 联动 |
| fixed_interval | 按固定时长分桶 | 跨时区语义一致 |
| time_zone | 分桶时区 | 不设则按 UTC 分 |
| min_doc_count | 桶内最小文档数 | 设 0 才返回空桶 |
| extended_bounds | 强制时间轴范围 | 补齐首尾空白区间 |
| offset | 整体平移分桶边界 | 对齐非整点班次 |
结果的 key 是毫秒时间戳,key_as_string 是按 format 与时区格式化后的字符串,展示层用后者更直观,程序取值用前者更稳。
默认 min_doc_count 为 0 时会返回空桶,但只覆盖有数据的区间;要固定连续时间轴用 extended_bounds 或 min_doc_count: 0 配合范围查询。
calendar_interval 与 fixed_interval 同时传会直接报错,二者只能选一个;按月分桶必须用 calendar_interval,固定 30 天与自然月不是一回事。
分桶粒度与时区实践
- 按天统计用 calendar_interval: day 并显式设置 time_zone
- 跨月对比用 month 粒度,固定 30 天与自然月语义不同
- 定位流量高峰用小时或 30 分钟粒度,再细容易超桶上限
- 空桶补齐用 min_doc_count: 0 配合 extended_bounds
- 桶内再嵌套 terms 时桶数会相乘,注意 max_buckets 限制
- 图表展示用 key_as_string,程序判空用 key