iT邦幫忙

第 12 屆 iT 邦幫忙鐵人賽

DAY 16
0

Mapping Part IV(結構)

這篇是介紹field data types的第二篇
介紹的field data types是我認為用到的機率比較高或是個人比較常用的


date field type
JSON並沒有date 的data type,所以在es可以用一下任一種來表達:

  • string且是 formatted dates (格式化的日期),例如:"2015-01-01""2015/01/01 12:10:30"
  • long number,代表是 milliseconds-since-the-epoch
  • integer,代表是 seconds-since-the-epoch

date formats 是可以透過參數 format 來指定的,而如果沒有設定,
則會用預設值 "strict_date_optional_time||epoch_millis"
代表著你針對此field輸入的值(timestamp),會被轉換成 strict_date_optional_timeepoch_millis

如果使用 milliseconds-since-the-epochseconds-since-the-epoch 必須是非負值,
而如果想要使用的日期是 1970以前的,則使用 格式化日期 (上述第一種)

在es內部,會把 dates(日期) 轉為UTC ,而且儲存為 long number,也就是 milliseconds-since-the-epoch
dates 做搜尋時,會轉換成用 range queries 搭配 long number,
aggs 的結果會轉換為 date format string,即使在新增資料時是輸入 long number

Request

PUT my-index-000004
{
  "mappings": {
    "properties": {
      "date": {
        "type": "date" (1)
      }
    }
  }
}

PUT my-index-000004/_doc/1
{ "date": "2015-01-01" } (2)

PUT my-index-000004/_doc/2
{ "date": "2015-01-01T12:10:30Z" } (3)

PUT my-index-000004/_doc/3
{ "date": 1420070400001 } (4)

PUT my-index-000004/_doc/4
{ "date": "2020-09-29T01:11:39+00:00" }

PUT my-index-000004/_doc/5
{ "date": "2020-09-29T01:11:39+08:00" } (5)

(1): 此 date field 沒有指定 format,所以使用了預設的 format,即為 "strict_date_optional_time||epoch_millis"
(2): string 且為 formatted dates
(3): string 且為 formatted dates ,多包含了time
(4): long number,使用 milliseconds-since-the-epoch
(5): string 且為 formatted dates ,多加了時區

look up sort values

GET my-index-000004/_search
{
  "sort": { "date": "desc"}
}

Response
Response

Response說明
回傳的 sort values都是 milliseconds-since-the-epoch

除了上述使用預設的 format,也可以自定義

更新mapping

p.s. 我直接在剛剛建的index,更改mapping,多加一個欄位 formatted_dates

PUT my-index-000004/_mapping
{
  "properties": {
    "formatted_dates": {
      "type": "date",
      "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis" (1)
    }
  }
}

(1): 可以用 || 分隔來指定多個 format

在新增document時,此field的data會依據定義的 format 做轉換,如果不符格式,則會用下一個比對,直到有符合的格式即停止,如果都不符合則新增document失敗

以此指定的format,新增下述的範例資料是會失敗的
"formatted_dates": "2020-09-29 01:11"

"formatted_dates": "2020-09-29T01:11:39"

"formatted_dates": "2020-09-29T01:11:39+08:00"
等等,可以自己玩玩看~


alias field type
針對index內的某field,定義他的 alternate name (替代名/別名)
此 alias 可在 search requests 中使用他來代替原本的target field(目標field)

index with alias field

PUT trips
{
  "mappings": {
    "properties": {
      "distance": {
        "type": "long"
      },
      "route_length_miles": {
        "type": "alias",
        "path": "distance" (1)
      }
    }
  }
}

(1): path 指向target field(目標field),注意這邊要是 full path

search alias field

GET trips/_search
{
  "query": {
    "range": {
      "route_length_miles": { (1)
        "gte": 39
      }
    }
  }
}

(1): 搜尋 field with alias field data type

不過使用 alias field data type還是有一些限制的,
像是 alias 的 target field 不能是 objectalias field type,
在建立 alias field 時,指定的 target field 必須已經被建立
此外,像是 新增/更新 document 的request都不能用在 alias field


ip field type
可儲存 IPv4 或 IPv6 位址

而大部分搜尋ip的方式都是用CIDR notation,也就是 [ip_address]/[prefix_length]
e.g.,

GET my-index-000005/_search
{
  "query": {
    "term": {
      "ip_addr": "192.168.0.0/16"
    }
  }
}

Range
Range field types代表的是在上下界(upper/lower bound)之間連續範圍的數值
例如:一個範圍可以是 兩個日期 或 任兩個integer,
其中在定義的時候,下界(lower bound)可用 gt (大於) 或 gte (大於等於),而上界(upper bound)可用 lt (小於) 或 lte (小於等於)
Range field是可以被用來搜尋的,而 aggs 是有限的支援

range types有以下幾種:integer_range, float_range, long_range, double_range, date_range, ip_range

直接用範例

Example 1: date_range

Create index with mapping

PUT range_index
{
  "mappings": {
    "properties": {
      "expected_attendees": {
        "type": "integer_range"
      },
      "time_frame": {
        "type": "date_range", (1)
        "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
      }
    }
  }
}

(1): date_range 即為 a range of date values,也接受和 date type一樣的參數,像是 format

index sample document

PUT range_index/_doc/1?refresh
{
  "expected_attendees" : { (1)
    "gte" : 10,
    "lt" : 20
  },
  "time_frame" : { (2)
    "gte" : "2015-10-31 12:00:00",
    "lte" : "2015-11-01"
  }
}

(1): 此輸入的值為 小於20且大於等於10
(2): format 符合上述定義,所以可正確輸入

這裡介紹比較特別的,
range query

GET range_index/_search
{
  "query": {
    "range": {
      "time_frame": {
        "gte": "2015-10-31",
        "lte": "2015-11-01",
        "relation": "within"
      }
    }
  }
}

range query 用在 range fields上時,可支援 relation 參數,可填入的值為:
-WITHIN: range field的值完全在搜尋的range值範圍
-CONTAINS: range field的值完全包含搜尋的range值
-INTERSECTS (default): range field的值和搜尋的range值有相交

Example 2: ip_range
ip的範圍,而 CIDR 正是可以表達範圍,所以可以輸入 CIDR notation

PUT range_index/_mapping
{
  "properties": {
    "ip_allowlist": {
      "type": "ip_range"
    }
  }
}

PUT range_index/_doc/2
{
  "ip_allowlist" : "192.168.0.0/16"
}

geo_point field type
儲存 latitude-longitude pairs (緯度-經度)
接受的格式很多種,包含了 string, object, geohash, array 等等
有個細節要注意一下,上述格式在儲存緯度經度的順序不是全部都一樣的,
例如:
object 和 string 都是 lat/lon (先緯度再經度),
而 arra y和 Well-Known Text POINT 都是 lon/lat (先經度再緯度)


其實還有蠻多特別的 field type,也有比較"專用"的,
像是 histogram, point, shape, dense_vector 等等 就不再多加說明了


如果有看到官網的文件,有些field type的頁面會顯示 X-Pack 的字樣,
X-Pack 是 elastic stack的extension(擴充元件),
根據不同等級,可以使用的功能會有所不同,
可到es官網訂閱其他等級,官方還做了很詳細的等級和功能表格,
不過官方非常好心,有提供30天試用,開放 X-Pack 所有功能


小小新手,如有理解錯誤或寫錯再請不吝提醒或糾正


Reference

Field data types
strict_date_optional_time


上一篇
Elastic Stack第十五重
下一篇
Elastic Stack第十七重
系列文
Elastic Stack武學練功坊30

尚未有邦友留言

立即登入留言