日期直方圖聚合
類似於直方圖的多桶聚合,但它只能應用於日期值,由於在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爲星期日。