工作坊實作內容

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
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

Last updated