1. 程式人生 > >Elasticsearch date 型別詳解

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

並作為儲存的格式。

在查詢日期時,會執行下面的過程:

  1. 轉換成 long 整形格式的範圍(range) 查詢
  2. 得到聚合的結果
  3. 將結果中的 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 格式,展示時根據不同格式而區分。

參考文件

  1. elasticsearch Date datatype