工作坊實作內容
DevOpsDays Taipei 2023 工作坊 - 如何在 Elasticsearch 實現敏捷的資料建模與管理
事先定義好的 Data Model
明確的欄位定義
Create Index or Update Mapping
PUT my-index
{
"mappings": {
"properties": {
"name": { "type": "text" },
"age": { "type": "integer" },
"birthday": { "type": "date" },
"email": { "type": "keyword" },
"salary": { "type": "double" }
}
}
}
PUT my-index/_mapping
{
"properties": {
"name": { "type": "text" },
"age": { "type": "integer" },
"birthday": { "type": "date" },
"email": { "type": "keyword" },
"salary": { "type": "double" }
}
}
Sprint 1: 收集電商訂單 Logs
配合的後端工程師告訴你,這個 Sprint 會完成一個訂單系統,右方是訂單的資料結構,每筆訂單完成都會產生一筆 Log 記錄到 Elasticsearch,未來 Data Team 會要用這些訂單資料做數據分析。
{
"currency": "EUR",
"customer_first_name": "Eddie",
"customer_gender": "MALE",
"customer_id": 38,
"customer_last_name": "Underwood",
"order_date": "2023-10-09T09:28:48+00:00",
"order_id": 584677,
"products": [
{
"base_price": 11.99,
"discount_percentage": 0,
"quantity": 1,
"manufacturer": "Elitelligence",
"tax_amount": 0,
"product_id": 6283,
"category": "Men's Clothing",
"sku": "ZO0549605496",
"taxless_price": 11.99,
"unit_discount_amount": 0,
"min_price": 6.35,
"_id": "sold_product_584677_6283",
"discount_amount": 0,
"created_on": "2016-12-26T09:28:48+00:00",
"product_name": "Basic T-shirt - dark blue/white",
"price": 11.99,
"taxful_price": 11.99,
"base_unit_price": 11.99
}
],
"total_quantity": 2,
"total_unique_products": 2,
"type": "order",
"user": "eddie"
}
溝通好會將訂單 Logs 資料寫入到 devopsdays-taipei-2023-ec-order 的 index 之中。
# 我們要先將這個 Order 的 Data Model 進行定義。
PUT devopsdays-taipei-2023-ec-order
{
"mappings": {
"properties": {
"currency": { "type": "keyword" },
"customer_first_name": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 }} },
"customer_gender": { "type": "keyword" },
"customer_id": { "type": "keyword" },
"customer_last_name": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 }} },
"order_date": { "type": "date" },
"order_id": { "type": "keyword" },
"products": {
"properties": {
"base_price": { "type": "double" },
"discount_percentage": { "type": "float" },
"quantity": { "type": "float" },
"manufacturer": { "type": "keyword" },
"tax_amount": { "type": "float" },
"product_id": { "type": "keyword" },
"category": { "type": "keyword" },
"sku": { "type": "keyword" },
"taxless_price": { "type": "double" },
"unit_discount_amount": { "type": "float" },
"min_price": { "type": "double" },
"_id": { "type": "keyword" },
"discount_amount": { "type": "float" },
"created_on": { "type": "date" },
"product_name": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 }} },
"price": { "type": "double" },
"taxful_price": { "type": "double" },
"base_unit_price": { "type": "double" }
}
},
"total_quantity": { "type": "float" },
"total_unique_products": { "type": "float" },
"type": { "type": "keyword" },
"user": { "type": "keyword" }
}
}
}
# 查看 mapping
GET devopsdays-taipei-2023-ec-order/_mapping
Testing Data for Sprint 1
# 第一批資料進來了
PUT devopsdays-taipei-2023-ec-order/_bulk
{ "index" : { "_id" : "584677" } }
{"currency":"EUR","customer_first_name":"Eddie","customer_gender":"MALE","customer_id":38,"customer_last_name":"Underwood","customer_phone":"","order_date":"2023-10-09T09:28:48+00:00","order_id":584677,"products":[{"base_price":11.99,"discount_percentage":0,"quantity":1,"manufacturer":"Elitelligence","tax_amount":0,"product_id":6283,"category":"Men's Clothing","sku":"ZO0549605496","taxless_price":11.99,"unit_discount_amount":0,"min_price":6.35,"_id":"sold_product_584677_6283","discount_amount":0,"created_on":"2016-12-26T09:28:48+00:00","product_name":"Basic T-shirt - dark blue/white","price":12,"taxful_price":12,"base_unit_price":12},{"base_price":24.99,"discount_percentage":0,"quantity":1,"manufacturer":"Oceanavigations","tax_amount":0,"product_id":19400,"category":"Men's Clothing","sku":"ZO0299602996","taxless_price":25,"unit_discount_amount":0,"min_price":11.75,"_id":"sold_product_584677_19400","discount_amount":0,"created_on":"2016-12-26T09:28:48+00:00","product_name":"Sweatshirt - grey multicolor","price":25,"taxful_price":25,"base_unit_price":25}],"taxful_total_price":37,"taxless_total_price":37,"total_quantity":2,"total_unique_products":2,"type":"order","user":"eddie"}
{ "index" : { "_id" : "584021" } }
{"currency":"EUR","customer_first_name":"Mary","customer_gender":"FEMALE","customer_id":20,"customer_last_name":"Bailey","customer_phone":"","order_date":"2023-10-08T21:59:02+00:00","order_id":584021,"products":[{"base_price":24.99,"discount_percentage":0,"quantity":1,"manufacturer":"Champion Arts","tax_amount":0,"product_id":11238,"category":"Women's Clothing","sku":"ZO0489604896","taxless_price":24.99,"unit_discount_amount":0,"min_price":11.75,"_id":"sold_product_584021_11238","discount_amount":0,"created_on":"2016-12-25T21:59:02+00:00","product_name":"Denim dress - black denim","price":24.99,"taxful_price":24.99,"base_unit_price":24.99},{"base_price":28.99,"discount_percentage":0,"quantity":1,"manufacturer":"Pyramidustries","tax_amount":0,"product_id":20149,"category":"Women's Clothing","sku":"ZO0185501855","taxless_price":28.99,"unit_discount_amount":0,"min_price":15.65,"_id":"sold_product_584021_20149","discount_amount":0,"created_on":"2016-12-25T21:59:02+00:00","product_name":"Shorts - black","price":28.99,"taxful_price":28.99,"base_unit_price":28.99}],"taxful_total_price":53.98,"taxless_total_price":53.98,"total_quantity":2,"total_unique_products":2,"type":"order","user":"mary"}
{ "index" : { "_id" : "584058" } }
{"currency":"EUR","customer_first_name":"Gwen","customer_gender":"FEMALE","customer_id":26,"customer_last_name":"Butler","customer_phone":"","order_date":"2023-10-04T22:32:10+00:00","order_id":584058,"products":[{"base_price":99.99,"discount_percentage":0,"quantity":1,"manufacturer":"Low Tide Media","tax_amount":0,"product_id":22794,"category":"Women's Shoes","sku":"ZO0374603746","taxless_price":99.99,"unit_discount_amount":0,"min_price":46.01,"_id":"sold_product_584058_22794","discount_amount":0,"created_on":"2016-12-25T22:32:10+00:00","product_name":"Boots - Midnight Blue","price":99.99,"taxful_price":99.99,"base_unit_price":99.99},{"base_price":99.99,"discount_percentage":0,"quantity":1,"manufacturer":"Oceanavigations","tax_amount":0,"product_id":23386,"category":"Women's Clothing","sku":"ZO0272202722","taxless_price":99.99,"unit_discount_amount":0,"min_price":53.99,"_id":"sold_product_584058_23386","discount_amount":0,"created_on":"2016-12-25T22:32:10+00:00","product_name":"Short coat - white/black","price":99.99,"taxful_price":99.99,"base_unit_price":99.99}],"taxful_total_price":199.98,"taxless_total_price":199.98,"total_quantity":2,"total_unique_products":2,"type":"order","user":"gwen"}
# 工程師反應,查看資料有誤?
GET devopsdays-taipei-2023-ec-order/_search
{
"query": {
"range": {
"taxful_total_price": {
"lte": 53
}
}
}
}
# 查看 mapping
GET devopsdays-taipei-2023-ec-order/_mapping
# 嘗試修復
PUT devopsdays-taipei-2023-ec-order/_mapping
{
"properties": {
"taxful_total_price": { "type": "double" },
"taxless_total_price": { "type": "double" }
}
}
Sprint 2: Index Mapping 的版本选代
# 刪除 index
DELETE devopsdays-taipei-2023-ec-order
# 建立 Index Template
# 包含 `_meta` 資料,以及 `aliases`。
PUT _index_template/devopsdays-taipei-2023-ec-order
{
"index_patterns": [
"devopsdays-taipei-2023-ec-order*"
],
"template": {
"aliases": {
"devopsdays-taipei-2023-ec-order": {}
},
"mappings": {
"_meta": {
"version": 1,
"version_creation_date": "2023-09-26"
},
"properties": {
"currency": { "type": "keyword" },
"customer_first_name": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 }} },
"customer_gender": { "type": "keyword" },
"customer_id": { "type": "keyword" },
"customer_last_name": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 }} },
"order_date": { "type": "date" },
"order_id": { "type": "keyword" },
"products": {
"properties": {
"base_price": { "type": "double" },
"discount_percentage": { "type": "float" },
"quantity": { "type": "float" },
"manufacturer": { "type": "keyword" },
"tax_amount": { "type": "float" },
"product_id": { "type": "keyword" },
"category": { "type": "keyword" },
"sku": { "type": "keyword" },
"taxless_price": { "type": "double" },
"unit_discount_amount": { "type": "float" },
"min_price": { "type": "double" },
"_id": { "type": "keyword" },
"discount_amount": { "type": "float" },
"created_on": { "type": "date" },
"product_name": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 }} },
"price": { "type": "double" },
"taxful_price": { "type": "double" },
"base_unit_price": { "type": "double" }
}
},
"taxful_total_price": { "type": "double" },
"taxless_total_price": { "type": "double" },
"total_quantity": { "type": "float" },
"total_unique_products": { "type": "float" },
"type": { "type": "keyword" },
"user": { "type": "keyword" }
}
}
},
"priority": 100,
"version": 1,
"_meta": {
"description": "devopsdays workshop",
"version_creation_date": "2023-09-26"
}
}
# 這次我們將 Index 名字後面加上 `_v1`,用來區別這是第一版,重新將資料匯入。
PUT devopsdays-taipei-2023-ec-order_v1/_bulk
{ "index" : { "_id" : "584677" } }
{"currency":"EUR","customer_first_name":"Eddie","customer_gender":"MALE","customer_id":38,"customer_last_name":"Underwood","customer_phone":"","order_date":"2023-10-09T09:28:48+00:00","order_id":584677,"products":[{"base_price":11.99,"discount_percentage":0,"quantity":1,"manufacturer":"Elitelligence","tax_amount":0,"product_id":6283,"category":"Men's Clothing","sku":"ZO0549605496","taxless_price":11.99,"unit_discount_amount":0,"min_price":6.35,"_id":"sold_product_584677_6283","discount_amount":0,"created_on":"2016-12-26T09:28:48+00:00","product_name":"Basic T-shirt - dark blue/white","price":12,"taxful_price":12,"base_unit_price":12},{"base_price":24.99,"discount_percentage":0,"quantity":1,"manufacturer":"Oceanavigations","tax_amount":0,"product_id":19400,"category":"Men's Clothing","sku":"ZO0299602996","taxless_price":25,"unit_discount_amount":0,"min_price":11.75,"_id":"sold_product_584677_19400","discount_amount":0,"created_on":"2016-12-26T09:28:48+00:00","product_name":"Sweatshirt - grey multicolor","price":25,"taxful_price":25,"base_unit_price":25}],"taxful_total_price":37,"taxless_total_price":37,"total_quantity":2,"total_unique_products":2,"type":"order","user":"eddie"}
{ "index" : { "_id" : "584021" } }
{"currency":"EUR","customer_first_name":"Mary","customer_gender":"FEMALE","customer_id":20,"customer_last_name":"Bailey","customer_phone":"","order_date":"2023-10-08T21:59:02+00:00","order_id":584021,"products":[{"base_price":24.99,"discount_percentage":0,"quantity":1,"manufacturer":"Champion Arts","tax_amount":0,"product_id":11238,"category":"Women's Clothing","sku":"ZO0489604896","taxless_price":24.99,"unit_discount_amount":0,"min_price":11.75,"_id":"sold_product_584021_11238","discount_amount":0,"created_on":"2016-12-25T21:59:02+00:00","product_name":"Denim dress - black denim","price":24.99,"taxful_price":24.99,"base_unit_price":24.99},{"base_price":28.99,"discount_percentage":0,"quantity":1,"manufacturer":"Pyramidustries","tax_amount":0,"product_id":20149,"category":"Women's Clothing","sku":"ZO0185501855","taxless_price":28.99,"unit_discount_amount":0,"min_price":15.65,"_id":"sold_product_584021_20149","discount_amount":0,"created_on":"2016-12-25T21:59:02+00:00","product_name":"Shorts - black","price":28.99,"taxful_price":28.99,"base_unit_price":28.99}],"taxful_total_price":53.98,"taxless_total_price":53.98,"total_quantity":2,"total_unique_products":2,"type":"order","user":"mary"}
{ "index" : { "_id" : "584058" } }
{"currency":"EUR","customer_first_name":"Gwen","customer_gender":"FEMALE","customer_id":26,"customer_last_name":"Butler","customer_phone":"","order_date":"2023-10-04T22:32:10+00:00","order_id":584058,"products":[{"base_price":99.99,"discount_percentage":0,"quantity":1,"manufacturer":"Low Tide Media","tax_amount":0,"product_id":22794,"category":"Women's Shoes","sku":"ZO0374603746","taxless_price":99.99,"unit_discount_amount":0,"min_price":46.01,"_id":"sold_product_584058_22794","discount_amount":0,"created_on":"2016-12-25T22:32:10+00:00","product_name":"Boots - Midnight Blue","price":99.99,"taxful_price":99.99,"base_unit_price":99.99},{"base_price":99.99,"discount_percentage":0,"quantity":1,"manufacturer":"Oceanavigations","tax_amount":0,"product_id":23386,"category":"Women's Clothing","sku":"ZO0272202722","taxless_price":99.99,"unit_discount_amount":0,"min_price":53.99,"_id":"sold_product_584058_23386","discount_amount":0,"created_on":"2016-12-25T22:32:10+00:00","product_name":"Short coat - white/black","price":99.99,"taxful_price":99.99,"base_unit_price":99.99}],"taxful_total_price":199.98,"taxless_total_price":199.98,"total_quantity":2,"total_unique_products":2,"type":"order","user":"gwen"}
# 檢查 `taxful_total_price` 與 `taxless_total_price` 的型態
GET devopsdays-taipei-2023-ec-order/_mapping
# 重新查詢,現在已正常
GET devopsdays-taipei-2023-ec-order/_search
{
"query": {
"range": {
"taxful_total_price": {
"lte": 53
}
}
}
}
動態新增欄位 Dynamic Mapping
Dynamic Template 範例
將 String 型態的欄位,定義成
keyword
,而不是預設的text
+keyword
。
PUT my-index
{
"mappings": {
"dynamic_templates": [
{
"keyword_strings": {
"match_mapping_type": "string",
"mapping": {
"type": "keyword"
}
}
}
]
}
}
將 String 型態的欄位,且欄位名字是
long_
開頭,同時不是_text
結尾,就定義成long
型態。
PUT my-index/
{
"mappings": {
"dynamic_templates": [
{
"string_as_long": {
"match_mapping_type": "string",
"match": "long_*",
"unmatch": "*_text",
"mapping": {
"type": "long"
}
}
}
]
}
}
將
name
物件裡除了middle
之外的所有欄位,都 copy 到full_name
的欄位,並指定為text
型態。
PUT my-index
{
"mappings": {
"dynamic_templates": [
{
"full_name": {
"path_match": "name.*",
"path_unmatch": "*.middle",
"mapping": {
"type": "text",
"copy_to": "full_name"
}
}
}
]
}
}
PUT my-index/_doc/1
{
"name": {
"first": "John",
"middle": "Winston",
"last": "Lennon"
}
}
先針對字串欄位給予定義,再來針對所有非字串的欄位,關閉
doc_values
。
PUT my-index
{
"mappings": {
"dynamic_templates": [
{
"named_analyzers": {
"match_mapping_type": "string",
"match": "*",
"mapping": {
"type": "text",
"analyzer": "{name}"
}
}
},
{
"no_doc_values": {
"match_mapping_type":"*",
"mapping": {
"type": "{dynamic_type}",
"doc_values": false
}
}
}
]
}
}
PUT my-index/_doc/1
{
"english": "Some English text",
"count": 5
}
Sprint 3: 建立適用的 Dynamic Template
# 定義好新的 Dynamic template 設定,同時移除不必要的 mapping 宣告,只剩下 `total_unique_products` 這個例外狀況需要特別宣告。
PUT _index_template/devopsdays-taipei-2023-ec-order
{
"index_patterns": [
"devopsdays-taipei-2023-ec-order*"
],
"template": {
"aliases": {
"devopsdays-taipei-2023-ec-order": {}
},
"mappings": {
"_meta": {
"version": 1,
"version_creation_date": "2023-09-26"
},
"dynamic_templates": [
{
"id": {
"match": "*_id",
"mapping": {
"type": "keyword"
}
}
},
{
"number_double": {
"match": ["*_price", "price"],
"mapping": {
"type": "double"
}
}
},
{
"number_float": {
"match": ["*_amount", "*_percentage", "quantity", "*_quantity"],
"mapping": {
"type": "float"
}
}
},
{
"date": {
"match": ["*_date", "created_on"],
"match_mapping_type": "date",
"mapping": {
"type": "date"
}
}
},
{
"string_as_text": {
"match": ["*_name"],
"match_mapping_type": "string",
"mapping": {
"type": "text",
"fields": {
"keyword": { "type": "keyword", "ignore_above": 256 }
}
}
}
},
{
"string_as_keyword": {
"match_mapping_type": "string",
"mapping": {
"type": "keyword"
}
}
}
],
"properties": {
"total_unique_products": { "type": "float" }
}
}
},
"priority": 100,
"version": 1,
"_meta": {
"description": "devopsdays workshop",
"version_creation_date": "2023-09-26"
}
}
# 偷偷刪掉資料
DELETE devopsdays-taipei-2023-ec-order_v1
# 重新匯入資料測試一下
PUT devopsdays-taipei-2023-ec-order_v1/_bulk
{ "index" : { "_id" : "584677" } }
{"currency":"EUR","customer_first_name":"Eddie","customer_gender":"MALE","customer_id":38,"customer_last_name":"Underwood","customer_phone":"","order_date":"2023-10-09T09:28:48+00:00","order_id":584677,"products":[{"base_price":11.99,"discount_percentage":0,"quantity":1,"manufacturer":"Elitelligence","tax_amount":0,"product_id":6283,"category":"Men's Clothing","sku":"ZO0549605496","taxless_price":11.99,"unit_discount_amount":0,"min_price":6.35,"_id":"sold_product_584677_6283","discount_amount":0,"created_on":"2016-12-26T09:28:48+00:00","product_name":"Basic T-shirt - dark blue/white","price":12,"taxful_price":12,"base_unit_price":12},{"base_price":24.99,"discount_percentage":0,"quantity":1,"manufacturer":"Oceanavigations","tax_amount":0,"product_id":19400,"category":"Men's Clothing","sku":"ZO0299602996","taxless_price":25,"unit_discount_amount":0,"min_price":11.75,"_id":"sold_product_584677_19400","discount_amount":0,"created_on":"2016-12-26T09:28:48+00:00","product_name":"Sweatshirt - grey multicolor","price":25,"taxful_price":25,"base_unit_price":25}],"taxful_total_price":37,"taxless_total_price":37,"total_quantity":2,"total_unique_products":2,"type":"order","user":"eddie"}
{ "index" : { "_id" : "584021" } }
{"currency":"EUR","customer_first_name":"Mary","customer_gender":"FEMALE","customer_id":20,"customer_last_name":"Bailey","customer_phone":"","order_date":"2023-10-08T21:59:02+00:00","order_id":584021,"products":[{"base_price":24.99,"discount_percentage":0,"quantity":1,"manufacturer":"Champion Arts","tax_amount":0,"product_id":11238,"category":"Women's Clothing","sku":"ZO0489604896","taxless_price":24.99,"unit_discount_amount":0,"min_price":11.75,"_id":"sold_product_584021_11238","discount_amount":0,"created_on":"2016-12-25T21:59:02+00:00","product_name":"Denim dress - black denim","price":24.99,"taxful_price":24.99,"base_unit_price":24.99},{"base_price":28.99,"discount_percentage":0,"quantity":1,"manufacturer":"Pyramidustries","tax_amount":0,"product_id":20149,"category":"Women's Clothing","sku":"ZO0185501855","taxless_price":28.99,"unit_discount_amount":0,"min_price":15.65,"_id":"sold_product_584021_20149","discount_amount":0,"created_on":"2016-12-25T21:59:02+00:00","product_name":"Shorts - black","price":28.99,"taxful_price":28.99,"base_unit_price":28.99}],"taxful_total_price":53.98,"taxless_total_price":53.98,"total_quantity":2,"total_unique_products":2,"type":"order","user":"mary"}
{ "index" : { "_id" : "584058" } }
{"currency":"EUR","customer_first_name":"Gwen","customer_gender":"FEMALE","customer_id":26,"customer_last_name":"Butler","customer_phone":"","order_date":"2023-10-04T22:32:10+00:00","order_id":584058,"products":[{"base_price":99.99,"discount_percentage":0,"quantity":1,"manufacturer":"Low Tide Media","tax_amount":0,"product_id":22794,"category":"Women's Shoes","sku":"ZO0374603746","taxless_price":99.99,"unit_discount_amount":0,"min_price":46.01,"_id":"sold_product_584058_22794","discount_amount":0,"created_on":"2016-12-25T22:32:10+00:00","product_name":"Boots - Midnight Blue","price":99.99,"taxful_price":99.99,"base_unit_price":99.99},{"base_price":99.99,"discount_percentage":0,"quantity":1,"manufacturer":"Oceanavigations","tax_amount":0,"product_id":23386,"category":"Women's Clothing","sku":"ZO0272202722","taxless_price":99.99,"unit_discount_amount":0,"min_price":53.99,"_id":"sold_product_584058_23386","discount_amount":0,"created_on":"2016-12-25T22:32:10+00:00","product_name":"Short coat - white/black","price":99.99,"taxful_price":99.99,"base_unit_price":99.99}],"taxful_total_price":199.98,"taxless_total_price":199.98,"total_quantity":2,"total_unique_products":2,"type":"order","user":"gwen"}
# 檢查 mapping 的型態
GET devopsdays-taipei-2023-ec-order/_mapping
無法事先定義好 Data Model
Runtime Field 的使用方式
在 Searching 時指定 Runtime Field
Searching 時指定 runtime field
# 定義 `@timestamp` 欄位為 date
PUT rf_test
{
"mappings": {
"properties": {
"@timestamp": {
"type": "date"
}
}
}
}
# Import Test Data
POST rf_test/_bulk?refresh=true
{"index":{}}
{"@timestamp":1516729294000,"model_number":"QVKC92Q","measures":{"voltage":"5.2","start": "300","end":"8675309"}}
{"index":{}}
{"@timestamp":1516642894000,"model_number":"QVKC92Q","measures":{"voltage":"5.8","start": "300","end":"8675309"}}
{"index":{}}
{"@timestamp":1516556494000,"model_number":"QVKC92Q","measures":{"voltage":"5.1","start": "300","end":"8675309"}}
{"index":{}}
{"@timestamp":1516470094000,"model_number":"QVKC92Q","measures":{"voltage":"5.6","start": "300","end":"8675309"}}
{"index":{}}
{"@timestamp":1516383694000,"model_number":"HG537PU","measures":{"voltage":"4.2","start": "400","end":"8625309"}}
{"index":{}}
{"@timestamp":1516297294000,"model_number":"HG537PU","measures":{"voltage":"4.0","start": "400","end":"8625309"}}
GET rf_test
# 定義 `runtime_mapping` 並編寫從 `doc_value` 將資料拿出並進行處理的規則。
GET rf_test/_search
{
"runtime_mappings": {
"day_of_week": {
"type": "keyword",
"script": {
"source": "emit(doc['@timestamp'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ROOT))"
}
}
},
"fields": [
"day_of_week"
]
}
# 定義 `runtime_mapping` 並編寫從 `_source` 將資料拿出並進行處理的規則。
GET rf_test/_search
{
"runtime_mappings": {
"mode_number": {
"type": "keyword",
"script": {
"source": "emit(params._source.model_number)"
}
}
},
"fields": [
"model_number"
]
}
在 Mapping 中定義 Runtime Field
# 使用 update mapping API 將 runtime fields 定義進 index mapping 之中
PUT rf_test/_mapping
{
"runtime": {
"day_of_week": {
"type": "keyword",
"script": {
"source": "emit(doc['@timestamp'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ROOT))"
}
}
},
"properties": {
"@timestamp": {
"type": "date"
}
}
}
# 使用 _search 將 fields 查出
GET rf_test/_search?docvalue_fields=day_of_week
Sprint 4: 事先所定義的欄位不足
# 早期的做法
GET devopsdays-taipei-2023-ec-order/_search
{
"query": {
"script": {
"script": "doc['order_date'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ROOT) == 'Wednesday'"
}
}
}
GET devopsdays-taipei-2023-ec-order/_search
{
"size": 0,
"aggs": {
"day_of_week": {
"terms": {
"script": {
"source": "doc['order_date'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ROOT)"
}
}
}
}
}
# 現在可以定義成 Runtime Field
GET devopsdays-taipei-2023-ec-order/_search
{
"runtime_mappings": {
"day_of_week": {
"type": "keyword",
"script": "emit(doc['order_date'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ROOT))"
}
},
"fields": [
"day_of_week"
]
}
# Runtime Field 可以使用在 query
GET devopsdays-taipei-2023-ec-order/_search
{
"runtime_mappings": {
"day_of_week": {
"type": "keyword",
"script": "emit(doc['order_date'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ROOT))"
}
},
"fields": [
"day_of_week"
],
"query": {
"term": {
"day_of_week": "Wednesday"
}
}
}
# Runtime Field 也可以使用在 aggregation
GET devopsdays-taipei-2023-ec-order/_search
{
"runtime_mappings": {
"day_of_week": {
"type": "keyword",
"script": "emit(doc['order_date'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ROOT))"
}
},
"fields": [
"day_of_week"
],
"size": 0,
"aggs": {
"day_of_week": {
"terms": {
"field": "day_of_week"
}
}
}
}
# 確認好用法用,我們可以將 Runtime Field 定義在 Mapping 中,就不用每次 Search 時都要宣告
PUT devopsdays-taipei-2023-ec-order/_mapping
{
"runtime": {
"day_of_week": {
"type": "keyword",
"script": {
"source": "emit(doc['order_date'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ROOT))"
}
}
}
}
# 記得也要修改 Index Template,並且讓 Version 進版。
PUT _index_template/devopsdays-taipei-2023-ec-order
{
"index_patterns": [
"devopsdays-taipei-2023-ec-order*"
],
"template": {
"aliases": {
"devopsdays-taipei-2023-ec-order": {}
},
"mappings": {
"_meta": {
"version": 2,
"version_creation_date": "2023-09-26"
},
"dynamic_templates": [
{
"id": {
"match": "*_id",
"mapping": {
"type": "keyword"
}
}
},
{
"number_double": {
"match": ["*_price", "price"],
"mapping": {
"type": "double"
}
}
},
{
"number_float": {
"match": ["*_amount", "*_percentage", "quantity", "*_quantity"],
"mapping": {
"type": "float"
}
}
},
{
"date": {
"match": ["*_date", "created_on"],
"match_mapping_type": "date",
"mapping": {
"type": "date"
}
}
},
{
"string_as_text": {
"match": ["*_name"],
"match_mapping_type": "string",
"mapping": {
"type": "text",
"fields": {
"keyword": { "type": "keyword", "ignore_above": 256 }
}
}
}
},
{
"string_as_keyword": {
"match_mapping_type": "string",
"mapping": {
"type": "keyword"
}
}
}
],
"runtime": {
"day_of_week": {
"type": "keyword",
"script": {
"source": "emit(doc['order_date'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ROOT))"
}
}
},
"properties": {
"total_unique_products": { "type": "float" }
}
}
},
"priority": 100,
"version": 2,
"_meta": {
"description": "devopsdays workshop",
"version_creation_date": "2023-09-26"
}
}
Sprint 5: 當我們想將 Runtime Field 正式定義
# 在 Index Template 增加 `day_of_week` 的 schema on-write 欄位宣告,並且進版
PUT _index_template/devopsdays-taipei-2023-ec-order
{
"index_patterns": [
"devopsdays-taipei-2023-ec-order*"
],
"template": {
"aliases": {
"devopsdays-taipei-2023-ec-order": {}
},
"mappings": {
"_meta": {
"version": 3,
"version_creation_date": "2023-09-26"
},
"dynamic_templates": [
{
"id": {
"match": "*_id",
"mapping": {
"type": "keyword"
}
}
},
{
"number_double": {
"match": ["*_price", "price"],
"mapping": {
"type": "double"
}
}
},
{
"number_float": {
"match": ["*_amount", "*_percentage", "quantity", "*_quantity"],
"mapping": {
"type": "float"
}
}
},
{
"date": {
"match": ["*_date", "created_on"],
"match_mapping_type": "date",
"mapping": {
"type": "date"
}
}
},
{
"string_as_text": {
"match": ["*_name"],
"match_mapping_type": "string",
"mapping": {
"type": "text",
"fields": {
"keyword": { "type": "keyword", "ignore_above": 256 }
}
}
}
},
{
"string_as_keyword": {
"match_mapping_type": "string",
"mapping": {
"type": "keyword"
}
}
}
],
"runtime": {
"day_of_week": {
"type": "keyword",
"script": {
"source": "emit(doc['order_date'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ROOT))"
}
}
},
"properties": {
"total_unique_products": { "type": "float" },
"order_date": { "type": "date" },
"day_of_week": {
"type": "keyword",
"on_script_error": "fail",
"script": {
"source": "emit(doc['order_date'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ROOT))"
}
}
}
}
},
"priority": 100,
"version": 3,
"_meta": {
"description": "devopsdays workshop",
"version_creation_date": "2023-09-26"
}
}
# 將新的資料寫入到新的 index v2 之中
POST devopsdays-taipei-2023-ec-order_v2/_bulk?refresh=true
{ "index" : { "_id" : "584093" } }
{"currency":"EUR","customer_first_name":"Diane","customer_gender":"FEMALE","customer_id":22,"customer_last_name":"Chandler","customer_phone":"","order_date":"2023-10-08T22:58:05+00:00","order_id":584093,"products":[{"base_price":74.99,"discount_percentage":0,"quantity":1,"manufacturer":"Primemaster","tax_amount":0,"product_id":12304,"category":"Women's Shoes","sku":"ZO0360303603","taxless_price":74.99,"unit_discount_amount":0,"min_price":34.5,"_id":"sold_product_584093_12304","discount_amount":0,"created_on":"2016-12-25T22:58:05+00:00","product_name":"High heeled sandals - argento","price":74.99,"taxful_price":74.99,"base_unit_price":74.99},{"base_price":99.99,"discount_percentage":0,"quantity":1,"manufacturer":"Oceanavigations","tax_amount":0,"product_id":19587,"category":"Women's Clothing","sku":"ZO0272002720","taxless_price":99.99,"unit_discount_amount":0,"min_price":47.01,"_id":"sold_product_584093_19587","discount_amount":0,"created_on":"2016-12-25T22:58:05+00:00","product_name":"Classic coat - black","price":99.99,"taxful_price":99.99,"base_unit_price":99.99}],"taxful_total_price":174.98,"taxless_total_price":174.98,"total_quantity":2,"total_unique_products":2,"type":"order","user":"diane"}
{ "index" : { "_id" : "574916" } }
{"currency":"EUR","customer_first_name":"Eddie","customer_gender":"MALE","customer_id":38,"customer_last_name":"Weber","customer_phone":"","order_date":"2023-10-11T03:48:58+00:00","order_id":574916,"products":[{"base_price":59.99,"discount_percentage":0,"quantity":1,"manufacturer":"Elitelligence","tax_amount":0,"product_id":11262,"category":"Men's Clothing","sku":"ZO0542505425","taxless_price":59.99,"unit_discount_amount":0,"min_price":28.2,"_id":"sold_product_574916_11262","discount_amount":0,"created_on":"2016-12-19T03:48:58+00:00","product_name":"Winter jacket - black","price":59.99,"taxful_price":59.99,"base_unit_price":59.99},{"base_price":20.99,"discount_percentage":0,"quantity":1,"manufacturer":"Elitelligence","tax_amount":0,"product_id":15713,"category":"Men's Accessories","sku":"ZO0601306013","taxless_price":20.99,"unit_discount_amount":0,"min_price":10.7,"_id":"sold_product_574916_15713","discount_amount":0,"created_on":"2016-12-19T03:48:58+00:00","product_name":"Watch - green","price":20.99,"taxful_price":20.99,"base_unit_price":20.99}],"taxful_total_price":80.98,"taxless_total_price":80.98,"total_quantity":2,"total_unique_products":2,"type":"order","user":"eddie"}
{ "index" : { "_id" : "574586" } }
{"currency":"EUR","customer_first_name":"Diane","customer_gender":"FEMALE","customer_id":22,"customer_last_name":"Goodwin","customer_phone":"","order_date":"2023-10-04T21:44:38+00:00","order_id":574586,"products":[{"base_price":59.99,"discount_percentage":0,"quantity":1,"manufacturer":"Low Tide Media","tax_amount":0,"product_id":5419,"category":"Women's Shoes","sku":"ZO0376303763","taxless_price":59.99,"unit_discount_amount":0,"min_price":31.79,"_id":"sold_product_574586_5419","discount_amount":0,"created_on":"2016-12-18T21:44:38+00:00","product_name":"Winter boots - brown","price":59.99,"taxful_price":59.99,"base_unit_price":59.99},{"base_price":11.99,"discount_percentage":0,"quantity":1,"manufacturer":"Pyramidustries","tax_amount":0,"product_id":19325,"category":"Women's Clothing","sku":"ZO0212402124","taxless_price":11.99,"unit_discount_amount":0,"min_price":6.47,"_id":"sold_product_574586_19325","discount_amount":0,"created_on":"2016-12-18T21:44:38+00:00","product_name":"Shorts - dark blue/pink/dark green","price":11.99,"taxful_price":11.99,"base_unit_price":11.99}],"taxful_total_price":71.98,"taxless_total_price":71.98,"total_quantity":2,"total_unique_products":2,"type":"order","user":"diane"}
# 同時查詢 v1 與 v2 的資料,使用端沒有任何影響
GET devopsdays-taipei-2023-ec-order/_search
{
"query": {
"term": {
"day_of_week": "Wednesday"
}
}
}
# Aggregation 也一樣,使用端沒有任何影響
GET devopsdays-taipei-2023-ec-order/_search
{
"size": 0,
"aggs": {
"day_of_week": {
"terms": {
"field": "day_of_week"
}
}
}
}
Async Search
# 我們嘗試使用 _async_search 但是發現執行太快,不會觸發 async_search
POST devopsdays-taipei-2023-ec-order/_async_search
{
"size": 0,
"aggs": {
"test": {
"date_histogram": {
"field": "order_date",
"fixed_interval": "2d"
}
}
}
}
# 強制執行 `wait_for_completion_timeout=0` 讓查詢立刻先返回,即出現 async_search id
POST devopsdays-taipei-2023-ec-order/_async_search?wait_for_completion_timeout=0
{
"size": 0,
"aggs": {
"test": {
"date_histogram": {
"field": "order_date",
"fixed_interval": "2d"
}
}
}
}
# 使用 id 去查詢執行狀態
GET _async_search/status/<responsed_async_search_id>
# 再使用 id 去取得結果
GET _async_search/<responsed_async_search_id>
# 也可以使用 `keep_on_completion`
POST devopsdays-taipei-2023-ec-order/_async_search?keep_on_completion
{
"size": 0,
"aggs": {
"test": {
"date_histogram": {
"field": "order_date",
"fixed_interval": "2d"
}
}
}
}
# 用完記得要刪除,不然會留 5 天
DELETE _async_search/<responsed_async_search_id>
# 可使用 .async_search 觀察 docs 數量的變化
GET .async-search/_search?size=0
Data Model 的事後修改
Update by Query
# 加上 `joe` 的 tag
POST kibana_sample_data_logs/_update_by_query
{
"script": {
"source": "ctx._source.tags.add(params.tag)",
"lang": "painless",
"params": {
"tag": "joe"
}
},
"query": {
"match_all": {}
}
}
# 移掉 `joe 的 tag,使用 `wait_for_completion=false` 成為 background task
POST kibana_sample_data_logs/_update_by_query?wait_for_completion=false
{
"script": {
"source": "if (ctx._source.tags.contains(params.tag)) { ctx._source.tags.remove(ctx._source.tags.indexOf(params.tag)) }",
"lang": "painless",
"params": {
"tag": "joe"
}
},
"query": {
"match_all": {}
}
}
# 取得 task 結果
GET /_tasks/<task_id>
Sprint 6: 將舊資料也轉成 Schema on Write
# 針對 `_v1` 的 index,加上 `day_of_week` 的 explicit mapping 宣告
PUT devopsdays-taipei-2023-ec-order_v1/_mapping
{
"properties": {
"day_of_week": {
"type": "keyword",
"on_script_error": "fail",
"script": {
"source": "emit(doc['order_date'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ROOT))"
}
}
}
}
# 接著使用 _update_by_query 將資料重新讀出來並再 indexing 一遍。
POST devopsdays-taipei-2023-ec-order_v1/_update_by_query
{
"query": {
"match_all": {}
}
}
# 刪除先前定義的 runtime field - `day_of_week`
PUT devopsdays-taipei-2023-ec-order_v1/_mapping
{
"runtime": {
"day_of_week": null
}
}
# 我們可以看到最後的 mapping 定義
GET devopsdays-taipei-2023-ec-order_v1/_mapping
# 同時也可以看到查詢出來的結果,是包含 `day_of_week` 欄位的
GET devopsdays-taipei-2023-ec-order_v1/_search?docvalue_fields=day_of_week
Previous如何在 Elasticsearch 實現敏捷的資料建模與管理 @ DevOpsDays 2023NextElastic Observability 實作體驗坊 @ DevOpsDays 2022
Last updated