Elasticsearch date 型別詳解
引言
一直對 elasticsearch 中的 date 型別認識比較模糊,而且在使用中又比較常見,這次決定多花些時間,徹底弄懂它,希望能對用到的同學提供幫助。
注意:本文測試使用是 elasticsearch 6.3 版本,其他版本規則可能有所變化,如遇到不相容的情況,還請參考 官方文件
Date 資料型別
elasticsearch 資料是以 JSON 格式儲存的,而 JSON中是並沒有 date 資料型別,因此 Elasticsearch 中雖然有 date 型別,但在展示時卻要轉化成另外的格式。
date 型別在 Elasticsearch 展示的格式有下面幾種:
- 將日期時間格式化後的字串,如 "2015-01-01" 或者 "2015/01/01 12:10:30"
- long 型的整數,意義是 milliseconds-since-the-epoch,翻譯一下就是自 1970-01-01 00:00:00 UTC 以來經過的毫秒數。
- int 型的整數,意義是 seconds-since-the-epoch, 是指自 1970-01-01 00:00:00 UTC 以來經過的秒數。
後兩種的描述裡都包含 UTC ,什麼是 UTC 呢?
UTC(Universal Time Coordinated) 叫做世界統一時間,中國大陸和 UTC 的時差是 + 8 ,也就是 UTC+8。
不論 date 是什麼展示格式,在 Elasticsearch 內部儲存時都是轉換成 UTC,並且把時區也會計算進去,從而得到 milliseconds-since-the-epoch
在查詢日期時,會執行下面的過程:
- 轉換成 long 整形格式的範圍(range) 查詢
- 得到聚合的結果
- 將結果中的 date 型別(long 整型資料)根據 date format 欄位轉換回對應的展示格式
Date 的預設格式
Date 的格式化型別是可以通過 format 來指定的,如果沒有指定,就會使用預設的格式:
"strict_date_optional_time||epoch_millis"
這表示什麼意思呢?
先來弄懂 strict_date_optional_time
A generic ISO datetime parser where the date is mandatory and the time is
optional.Full details here.
這是 elasticsearch 官網的解釋,表示只要是 ISO datetime parser 可以正常解析的都是 strict_date_optional_time。都有哪些語法呢?
date-opt-time = date-element ['T' [time-element] [offset]]
date-element = std-date-element | ord-date-element | week-date-element
std-date-element = yyyy ['-' MM ['-' dd]]
ord-date-element = yyyy ['-' DDD]
week-date-element = xxxx '-W' ww ['-' e]
time-element = HH [minute-element] | [fraction]
minute-element = ':' mm [second-element] | [fraction]
second-element = ':' ss [fraction]
fraction = ('.' | ',') digit+
其中中括號內的都是可選的,可填可不填。以 std-date_element 舉個例子
2018-11-19
2018
2018-11
上面 3 種格式都滿足要求。
除了 strict_date_optional_time ,還可以是 epoch_millis 格式,即 epoch 以來的毫秒數。
舉個例子
PUT my_index
{
"mappings": {
"_doc": {
"properties": {
"date": {
"type": "date"
}
}
}
}
}
PUT my_index/_doc/1
{ "date": "2015-01-01" }
PUT my_index/_doc/2
{ "date": "2015-01-01T12:10:30Z" }
PUT my_index/_doc/3
{ "date": 1420070400001 }
GET my_index/_search
{
"sort": { "date": "asc"}
上面的 PUT 請求中的 date 資料均滿足預設的要求。
如何指定多個 date 格式?
同一個 date 欄位可以指定多個 date 格式,只要使用 ||
分隔就可以了。在索引,都會對 date 格式挨個進行匹配,直到找到匹配的格式為止。
如果儲存時 date 格式為 milliseconds-since-the-epoch ,在查詢時會將其轉換為指定的第一個 date 格式。
舉個例子,有興趣的同學可在 sense 中動手實踐下。
PUT my_index
{
"mappings": {
"doc": {
"properties": {
"date": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
}
}
}
}
}
PUT /my_index/doc/1
{ "date": "2018-09-24 19:23:45" }
PUT /my_index/doc/2
{ "date": "2018-09-25" }
GET my_index/_search
{
"query": {
"match_all": {}
}
}
小結
本文主要講解了 elsaticserach 中的 date 型別格式,語法及轉換過程。elasticsearch 中儲存 date 型別統一使用 milliseconds-since-the-epoch 格式,展示時根據不同格式而區分。