Elasticsearch 參考指南(日期直方圖聚合)

日期直方圖聚合

類似於直方圖的多桶聚合,但它只能應用於日期值,由於在Elasticsearch內部將日期表示爲long值,因此也可以在日期上使用普通的histogram,但準確性會受到影響,原因是基於時間的間隔不是固定的(想想閏年和一個月的天數),因此,我們需要對基於時間的數據提供特殊支持。從功能的角度來看,這個直方圖支持與普通直方圖相同的特性,主要的區別是間隔可以由日期/時間表達式指定。

請求桶間隔一個月。

POST /sales/_search?size=0
{
    "aggs" : {
        "sales_over_time" : {
            "date_histogram" : {
                "field" : "date",
                "interval" : "month"
            }
        }
    }
}

時間間隔可用的表達式:year1y)、quarter1q)、month1M)、week1w)、day1d)、hour1h)、minute1M)、second1s)。

時間值也可以通過時間單位解析所支持的縮寫來指定,注意,不支持小數時間值,但是你可以通過轉移到另一個時間單位來解決這個問題(例如,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:00time_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爲星期日。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章