日期直方图聚合
类似于直方图的多桶聚合,但它只能应用于日期值,由于在Elasticsearch内部将日期表示为long
值,因此也可以在日期上使用普通的histogram
,但准确性会受到影响,原因是基于时间的间隔不是固定的(想想闰年和一个月的天数),因此,我们需要对基于时间的数据提供特殊支持。从功能的角度来看,这个直方图支持与普通直方图相同的特性,主要的区别是间隔可以由日期/时间表达式指定。
请求桶间隔一个月。
POST /sales/_search?size=0
{
"aggs" : {
"sales_over_time" : {
"date_histogram" : {
"field" : "date",
"interval" : "month"
}
}
}
}
时间间隔可用的表达式:year
(1y
)、quarter
(1q
)、month
(1M
)、week
(1w
)、day
(1d
)、hour
(1h
)、minute
(1M
)、second
(1s
)。
时间值也可以通过时间单位解析所支持的缩写来指定,注意,不支持小数时间值,但是你可以通过转移到另一个时间单位来解决这个问题(例如,1.5h
可以被指定为90m
),还要注意,大于天的时间间隔不支持任意值,但只能是一个单位大(例如,1y
是有效的,2y
不是)。
POST /sales/_search?size=0
{
"aggs" : {
"sales_over_time" : {
"date_histogram" : {
"field" : "date",
"interval" : "90m"
}
}
}
}
键
在内部,日期被表示为64位数字,表示从纪元开始算起的时间戳,这些时间戳作为桶的key
返回,key_as_string
是与使用format
参数指定的格式转换成格式化日期字符串相同的时间戳:
如果没有指定format
,那么它将使用字段映射中指定的第一个日期格式。
POST /sales/_search?size=0
{
"aggs" : {
"sales_over_time" : {
"date_histogram" : {
"field" : "date",
"interval" : "1M",
"format" : "yyyy-MM-dd"
}
}
}
}
"format" : "yyyy-MM-dd"
=> 支持表达日期格式模式
响应:
{
...
"aggregations": {
"sales_over_time": {
"buckets": [
{
"key_as_string": "2015-01-01",
"key": 1420070400000,
"doc_count": 3
},
{
"key_as_string": "2015-02-01",
"key": 1422748800000,
"doc_count": 2
},
{
"key_as_string": "2015-03-01",
"key": 1425168000000,
"doc_count": 2
}
]
}
}
}
时区
在Elasticsearch中日期时间被存储在UTC,默认情况下,所有桶和四舍五入都是在UTC中完成的,可以使用time_zone
参数指示桶使用不同的时区。
时区可以指定为ISO 8601 UTC偏移量(例如+01:00
或-08:00
),也可以指定为时区id,这是TZ数据库(如America/Los_Angeles
)中使用的标识符。
考虑下面的示例:
PUT my_index/_doc/1?refresh
{
"date": "2015-10-01T00:30:00Z"
}
PUT my_index/_doc/2?refresh
{
"date": "2015-10-01T01:30:00Z"
}
GET my_index/_search?size=0
{
"aggs": {
"by_day": {
"date_histogram": {
"field": "date",
"interval": "day"
}
}
}
}
如果没有指定时区,则使用UTC,这将导致将这两个文档放入同一天的桶中,该桶从2015年10月1日午夜UTC开始:
{
...
"aggregations": {
"by_day": {
"buckets": [
{
"key_as_string": "2015-10-01T00:00:00.000Z",
"key": 1443657600000,
"doc_count": 2
}
]
}
}
}
如果指定了-01:00
的time_zone
,那么午夜从UTC午夜前一小时开始:
GET my_index/_search?size=0
{
"aggs": {
"by_day": {
"date_histogram": {
"field": "date",
"interval": "day",
"time_zone": "-01:00"
}
}
}
}
现在第一个文档落入2015年9月30日的桶,第二个文档落入2015年10月1日的桶:
{
...
"aggregations": {
"by_day": {
"buckets": [
{
"key_as_string": "2015-09-30T00:00:00.000-01:00",
"key": 1443574800000,
"doc_count": 1
},
{
"key_as_string": "2015-10-01T00:00:00.000-01:00",
"key": 1443661200000,
"doc_count": 1
}
]
}
}
}
key_as_string
值表示在指定时区中每天的午夜。
当使用遵循DST(夏令时)更改的时区时,与这些更改发生的时刻接近的桶的大小可能与使用interval
预期的大小略有不同。例如,考虑在CET
时区启动DST:2016年3月27日凌晨2点,时钟拨快1小时至当地时间凌晨3点,当使用day
作为interval
时,覆盖当天的桶将只保存23个小时的数据,而其他桶通常是24小时。对于较短的间隔,如12h,也是如此,在这里,当DST转变发生时,我们在3月27日早上只有一个11小时的桶。
偏移量
offset
参数用于通过指定的正(+
)或负偏移(-
)的持续时间来更改每个桶的起始值,例如1h
为1小时或1d
为一天,有关更多可能的持续时间选项,请参阅时间单位。
例如,当使用day
的间隔时,每个桶从午夜运行到午夜,将offset
参数设置为+6h
将更改每个桶从早上6点运行到早上6点:
PUT my_index/_doc/1?refresh
{
"date": "2015-10-01T05:30:00Z"
}
PUT my_index/_doc/2?refresh
{
"date": "2015-10-01T06:30:00Z"
}
GET my_index/_search?size=0
{
"aggs": {
"by_day": {
"date_histogram": {
"field": "date",
"interval": "day",
"offset": "+6h"
}
}
}
}
上面的请求将文档分组为从早上6点开始的桶,而不是从午夜开始的单个桶:
{
...
"aggregations": {
"by_day": {
"buckets": [
{
"key_as_string": "2015-09-30T06:00:00.000Z",
"key": 1443592800000,
"doc_count": 1
},
{
"key_as_string": "2015-10-01T06:00:00.000Z",
"key": 1443679200000,
"doc_count": 1
}
]
}
}
}
在进行time_zone
调整之后,计算每个桶的起始offset
。
keyed响应
将keyed
标志设置为true
将把唯一的字符串键与每个桶关联起来,并以hash而不是数组的形式返回范围:
POST /sales/_search?size=0
{
"aggs" : {
"sales_over_time" : {
"date_histogram" : {
"field" : "date",
"interval" : "1M",
"format" : "yyyy-MM-dd",
"keyed": true
}
}
}
}
响应:
{
...
"aggregations": {
"sales_over_time": {
"buckets": {
"2015-01-01": {
"key_as_string": "2015-01-01",
"key": 1420070400000,
"doc_count": 3
},
"2015-02-01": {
"key_as_string": "2015-02-01",
"key": 1422748800000,
"doc_count": 2
},
"2015-03-01": {
"key_as_string": "2015-03-01",
"key": 1425168000000,
"doc_count": 2
}
}
}
}
}
脚本
与普通直方图一样,支持文档级别脚本和值级别脚本,还可以使用order
设置控制返回的桶的顺序,并基于min_doc_count
设置过滤返回的桶(默认情况下,将返回匹配文档的第一个桶和最后一个桶之间的所有桶)。这个直方图还支持extended_bounds
设置,它允许扩展直方图的界限超过数据本身(关于为什么要这样做的更多信息,请参阅此处的解释)。
缺失值
missing
参数定义了如何处理缺失值的文档,默认情况下,它们将被忽略,但也可以将它们视为有值来处理。
POST /sales/_search?size=0
{
"aggs" : {
"sale_date" : {
"date_histogram" : {
"field" : "date",
"interval": "year",
"missing": "2000/01/01"
}
}
}
}
publish_date
字段中没有值的文档将落入具有值为2000-01-01
的文档的同一个桶。
顺序
默认情况下,返回的桶按key
升序排序,不过可以使用order
设置控制顺序行为,支持与Terms聚合相同的order
功能。
在6.0.0中已弃用
使用
_key
而不是_time
来根据它们的日期/键来排序桶。
使用脚本通过星期几聚合
在某些情况下,日期直方图不能帮助我们,例如,当我们需要通过星期几聚合结果时,在这种情况下,为了克服这个问题,我们可以使用一个返回星期几的脚本:
POST /sales/_search?size=0
{
"aggs": {
"dayOfWeek": {
"terms": {
"script": {
"lang": "painless",
"source": "doc['date'].value.dayOfWeek"
}
}
}
}
}
响应:
{
...
"aggregations": {
"dayOfWeek": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "7",
"doc_count": 4
},
{
"key": "4",
"doc_count": 3
}
]
}
}
}
响应将包含以星期为键的所有桶:1为星期一,2为星期二...7为星期日。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。