Elasticsearch 参考指南(日期直方图聚合)
日期直方图聚合
类似于直方图的多桶聚合,但它只能应用于日期值,由于在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值表示在指定时区中每天的午夜。
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为星期日。