Elasticsearch 的映射 (mapping)

有別於其他DB, elasticsearch 在使用時不用預先定義每個欄位的資料型態.
使用上雖然方便, 但也不是每次都那麼準確. 請看下面例子.


curl -XPOST "http://127.0.0.1:9200/myindex/doc?pretty" -d '{
"name": "John",
"age": 30
}'
{
  "_index" : "myindex",
  "_type" : "doc",
  "_id" : "AWMcg0UmWZXbD_Pu65Ay",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "created" : true
}

curl "http://127.0.0.1:9200/myindex/_mapping?pretty"
{
  "myindex" : {
    "mappings" : {
      "doc" : {
        "properties" : {
          "age" : {
            "type" : "long"
          },
          "name" : {
            "type" : "text",
            "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            }
          }
        }
      }
    }
  }
}

上面的示範中, 我們新增一筆資料

{ "name": "John", "age": 30 }

其中name, 被識別為text, 並且自帶出一個keyword欄位
age 被識別為long, 到目前為止, 都還算是妥妥的.

上面映射帶給你的效果

  • text: 可以用作通配符搜索
    curl "127.0.0.1:9200/myindex/_search?q=name:Joh*"

  • keyword: 一定要完全匹配才算命中

  • long: 可以做數字的聚合搜索, 或是範圍搜索
    curl -g '127.0.0.1:9200/myindex/_search?q=age:[20+TO+40]' | jq .


不過當如果遇到資料映射錯誤會發生什麼事呢?

輕則無法做聚合查詢, 搜尋不到; 重則資料無法寫入!

換句話說; 我們就可以明白, 當今天想搜尋3x歲的人的時候, 使用3x這種
搜尋是行不通的哦~


那我要怎麼定義自己的資料型態?

從上面的範例可以看到, 查詢映射的指令是 _mapping , 不過其實你下
curl 127.0.0.1:9200/myindex 也是看的到映射, 如下:

curl "127.0.0.1:9200/myindex?pretty"
{
  "myindex" : {
    "aliases" : { },
    "mappings" : {
      "doc" : {
        "properties" : {
          "age" : {
            "type" : "long"
          },
          "name" : {
            "type" : "text",
            "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            }
          }
        }
      }
    },
    "settings" : {
      "index" : {
        "creation_date" : "1525191754938",
        "number_of_shards" : "5",
        "number_of_replicas" : "1",
        "uuid" : "lPPTXdLPQAaS-rCTfdVMJA",
        "version" : {
          "created" : "5020299"
        },
        "provided_name" : "myindex"
      }
    }
  }
}

所以我們就知道一個索引(index)是由alias, mappings, settings 組成的.
有點偏題了.. 下面就介紹自定義映射的方式吧~


定義映射有兩種方式:

(一) 直接對個別的索引配置映射:

這種方式又有兩種方式可以達成..

  • 在創建索引的時候直接配置
curl -XPUT http://127.0.0.1:9200/myindex -d '{
    "mappings" : {
        "doc" : {
            "properties" : {
                "ip_addr" : { "type" : "ip" }
            }
        }
    }
}'
  • 索引創建後, 在加上配置 (可用於update現有配置)
curl -XPUT http://127.0.0.1:9200/myindex/_mapping/doc -d '{
    "properties" : {
        "ip_addr" : { "type" : "ip" }
    }
}'

可以看到兩者的差別, 僅是在一個url比較短, 一個比較長而已 (誤...
兩個可以達到一樣的效果, 但是如果你使用上面第一種, elasticsearch裡面就不能
有你指定的index, 否則...!!
他就會回你index已經存在 Σ(・ω・ノ)ノ ┴─┴


(二) 使用樣板映射(template):
這是我們最常使用的方式哦, 為什麼呢?
因為如果我們的索引是用天來區隔的, myindex-YYYY-MM-dd
也就是比如你配置了今天的映射, 明天又有一個全新的他出現了
就算你定義一個他, 還會有千千萬萬個他!!

ㄜ.. 言歸正傳, 開始吧.

所謂樣板, 就是說今天只要索引的名子, 有匹配到你預先定義的名字, 就會去自行配置
你的設定. 我們看看示範吧.

放入一個名子叫做mytemplate的模板, 匹配的對象是myindex*
效果就是id這個欄位要變成text

curl -XPUT http://127.0.0.1:9200/_template/mytemplate -d '{  
  "template": "myindex*",
  "mappings": {
    "doc": {
      "properties": {
        "id": {
          "type": "text"
        }
      }
    }
  }
}'

查看樣板可以用下面兩種方式(步驟): 這兩個方式都是可以看樣板, 第一個是可以看目前有哪些樣板, 第二種就是看詳細的內容啦~

先看目前有哪些:

curl "http://127.0.0.1:9200/_cat/templates?v"
name       template order version
mytemplate myindex* 0

name: 樣板名字
template: 匹配規則
order: 優先級別, 如果兩個樣板重複匹配到的話, 級別高的優先選擇
version: 版本號

再看詳細內容:

curl "http://127.0.0.1:9200/_template/mytemplate?pretty"
{
  "mytemplate" : {
    "order" : 0,
    "template" : "myindex*",
    "settings" : { },
    "mappings" : {
      "doc" : {
        "properties" : {
          "id" : {
            "type" : "text"
          }
        }
      }
    },
    "aliases" : { }
  }
}

來驗證吧!

# 首先創建兩個新的索引
# 我應該要命中
curl -XPOST 127.0.0.1:9200/myindex123/doc -d '{
	"id": 22567789
}'

# 我是來亂的
curl -XPOST 127.0.0.1:9200/my123index/doc -d '{
	"id": 33457789
}'

# 然後看一下兩個索引的映射狀態
# 看一下, 我真的成功映射到了
curl "127.0.0.1:9200/myindex123/_mapping?pretty"
{
  "myindex123" : {
    "mappings" : {
      "doc" : {
        "properties" : {
          "id" : {
            "type" : "text"
          }
        }
      }
    }
  }
}

# 看一下, 果然是來亂的..
curl "127.0.0.1:9200/my123index/_mapping?pretty"
{
  "my123index" : {
    "mappings" : {
      "doc" : {
        "properties" : {
          "id" : {
            "type" : "long"
          }
        }
      }
    }
  }
}



資料映射大致講到這邊囉~
有兩點需要特別注意的:

  • 一個索引裡面已存在的欄位 , 是不允許修改映射的
  • 一個索引去響應模板的配置 , 只有在新創建的時候