公號:碼農充電站pro
主頁:https://codeshellme.github.iohtml
ES 中的 Mapping 至關於傳統數據庫中的表定義,它有如下做用:git
一個 Mapping 是針對一個索引中的 Type 定義的:github
經過下面語法能夠獲取一個索引的 Mapping 信息:shell
GET index_name/_mapping
字段的 mapping 能夠設置不少參數,以下:數據庫
false
,表示數據僅作存儲,不支持搜索和聚合分析(數據保存在 _source 中)。
true
。false
,表示不創建倒排索引(節省空間),同時數據也沒法被搜索,但依然支持聚合分析,數據也會出如今 _source 中。true
。false
,可節省空間。true
。false
,以節省磁盤空間。
true
。true
。
false
。false
,數據存儲在 _source 中。
true
,false
,strict
。null
的值。讓一個字段擁有多個子字段類型,使得一個字段可以被多個不一樣的索引方式進行索引。數組
示例 1:app
PUT index_name { "mappings": { # 設置 mappings "properties": { # 屬性,固定寫法 "city": { # 字段名 "type": "text", # city 字段的類型爲 text "fields": { # 多字段域,固定寫法 "raw": { # 子字段名稱 "type": "keyword" # 子字段類型 } } } } } }
示例 2 :elasticsearch
PUT index_name { "mappings": { "properties": { "title": { # 字段名稱 "type": "text", # 字段類型 "analyzer": "english", # 字段分詞器 "fields": { # 多字段域,固定寫法 "std": { # 子字段名稱 "type": "text", # 子字段類型 "analyzer": "standard" # 子字段分詞器 } } } } } }
ES 中字段的數據類型有如下這些:ide
text 類型與 keyword 類型oop
字符串數據能夠定義成 text 或 keyword 類型,text 類型數據會作分詞處理,而 keyword 類型數據不會作分詞處理。
數組類型
對於數組類型 Arrays,ES 並無提供專門的數組類型,可是任何字段均可以包含多個相同類型的數據,好比:
["one", "two"] # 一個字符串數組 [1, 2] # 一個整數數組 [1, [ 2, 3 ]] # 至關於 [ 1, 2, 3 ] [{ "name": "Mary", "age": 12 }, { "name": "John", "age": 10 }] # 一個對象數組
當在 Mapping 中查看這些數組的類型時,其實仍是數組中的元素的類型,而不是一個數組類型。
Nested 是一種對象類型,它保留了子字段之間的關係。
假如咱們有以下結構的數據:
POST my_movies/_doc/1 { "title":"Speed", "actors":[ # actors 是一個數組類型,數組中的元素是對象類型 { "first_name":"Keanu", "last_name":"Reeves" }, { "first_name":"Dennis", "last_name":"Hopper" } ] }
將數據插入 ES 以後,執行下面的查詢:
# 查詢電影信息 POST my_movies/_search { "query": { "bool": { "must": [ {"match": {"actors.first_name": "Keanu"}}, {"match": {"actors.last_name": "Hopper"}} ] } } }
按照上面的查詢語句,咱們想查詢的是 first_name=Keanu
且 last_name=Hopper
的數據,因此咱們剛纔插入的 id 爲 1 的文檔應該不符合這個查詢條件。
可是在 ES 中執行上面的查詢語句,卻能查出 id 爲 1 的文檔。這是爲何呢?
這是由於,ES 對於這種 actors 字段這樣的結構的數據,ES 並無考慮對象的邊界。
實際上,在 ES 內部,id 爲 1 的那個文檔是這樣存儲的:
"title":"Speed" "actors.first_name":["Keanu","Dennis"] "actors.last_name":["Reeves","Hopper"]
因此這種存儲方式,並非咱們想象的那樣。
若是咱們查看 ES 默認爲上面(id 爲 1)結構的數據生成的 mappings,以下:
{ "my_movies" : { "mappings" : { "properties" : { "actors" : { # actors 內部又嵌套了一個 properties "properties" : { "first_name" : { # 定義 first_name 的類型 "type" : "text", "fields" : { "keyword" : {"type" : "keyword", "ignore_above" : 256} } }, "last_name" : { # 定義 last_name 的類型 "type" : "text", "fields" : { "keyword" : {"type" : "keyword", "ignore_above" : 256} } } } }, # end actors "title" : { "type" : "text", "fields" : { "keyword" : {"type" : "keyword", "ignore_above" : 256} } } } } } }
那如何才能真正的表達一個對象類型呢?這就須要使用到 Nested 類型。
Nested 類型容許對象數組中的對象被獨立(看做一個總體)索引。
咱們對 my_movies 索引設置這樣的 mappings:
DELETE my_movies PUT my_movies { "mappings" : { "properties" : { "actors" : { "type": "nested", # 將 actors 設置爲 nested 類型 "properties" : { # 這時 actors 數組中的每一個對象就是一個總體了 "first_name" : {"type" : "keyword"}, "last_name" : {"type" : "keyword"} }}, "title" : { "type" : "text", "fields" : {"keyword":{"type":"keyword","ignore_above":256}} } } } }
寫入數據後,在進行這樣的搜索,就不會搜索出數據了:
# 查詢電影信息 POST my_movies/_search { "query": { "bool": { "must": [ {"match": {"actors.first_name": "Keanu"}}, {"match": {"actors.last_name": "Hopper"}} ] } } }
可是這樣的查詢也查不出數據:
POST my_movies/_search { "query": { "bool": { "must": [ {"match": {"actors.first_name": "Keanu"}}, {"match": {"actors.last_name": "Reeves"}} ] } } }
這是由於,查詢 Nested 類型的數據,要像下面這樣查詢:
POST my_movies/_search { "query": { "bool": { "must": [ { "nested": { # nested 查詢 "path": "actors", # 自定 actors 字段路徑 "query": { # 查詢語句 "bool": { "must": [ {"match": {"actors.first_name": "Keanu"}}, {"match": {"actors.last_name": "Hopper"}} ] } } } # end nested } ] # end must } # end bool } }
對 Nested 類型的數據進行聚合,示例:
# Nested Aggregation POST my_movies/_search { "size": 0, "aggs": { "actors": { # 自定義聚合名稱 "nested": { # 指定 nested 類型 "path": "actors" # 聚合的字段名稱 }, "aggs": { # 子聚合 "actor_name": { # 自定義子聚合名稱 "terms": { # terms 聚合 "field": "actors.first_name", # 子字段名稱 "size": 10 } } } } } }
使用普通的聚合方式則沒法工做:
POST my_movies/_search { "size": 0, "aggs": { "actors": { # 自定義聚合名稱 "terms": { # terms 聚合 "field": "actors.first_name", "size": 10 } } } }
Nested 類型的對象與其父/子級文檔的關係,使得每次文檔有更新的時候須要重建整個文檔(包括根對象和嵌套對象)的索引。
Join 數據類型(相似關係型數據庫中的 Join 操做)爲同一索引中的文檔定義父/子關係。
Join 數據類型能夠維護一個父/子關係,從而分離兩個對象,它的優勢是:
Nested 類型與 Join(Parent/Child) 類型的優缺點對比:
定義 Join 類型的語法以下:
DELETE my_blogs # 設定 Parent/Child Mapping PUT my_blogs { "mappings": { "properties": { "blog_comments_relation": { # 字段名稱 "type": "join", # 定義 join 類型 "relations": { # 定義父子關係 "blog": "comment" # blog 表示父級文檔,comment 表示子級文檔 } }, "content": { "type": "text" }, "title": { "type": "keyword" } } } }
先插入兩個父文檔:
# 插入 blog1 PUT my_blogs/_doc/blog1 { "title":"Learning Elasticsearch", "content":"learning ELK @ geektime", "blog_comments_relation":{ "name":"blog" # name 爲 blog 表示父文檔 } } # 插入 blog2 PUT my_blogs/_doc/blog2 { "title":"Learning Hadoop", "content":"learning Hadoop", "blog_comments_relation":{ "name":"blog" # name 爲 blog 表示父文檔 } }
插入子文檔:
# 插入comment1 PUT my_blogs/_doc/comment1?routing=blog1 # routing 的值是父文檔 id { # 確保父子文檔被索引到相同的分片 "comment":"I am learning ELK", "username":"Jack", "blog_comments_relation":{ "name":"comment", # name 爲 comment 表示子文檔 "parent":"blog1" # 指定父文檔的 id,表示子文檔屬於哪一個父文檔 } } # 插入 comment2 PUT my_blogs/_doc/comment2?routing=blog2 # routing 的值是父文檔 id { # 確保父子文檔被索引到相同的分片 "comment":"I like Hadoop!!!!!", "username":"Jack", "blog_comments_relation":{ "name":"comment", # name 爲 comment 表示子文檔 "parent":"blog2" # 指定父文檔的 id,表示子文檔屬於哪一個父文檔 } } # 插入 comment3 PUT my_blogs/_doc/comment3?routing=blog2 # routing 的值是父文檔 id { # 確保父子文檔被索引到相同的分片 "comment":"Hello Hadoop", "username":"Bob", "blog_comments_relation":{ "name":"comment", # name 爲 comment 表示子文檔 "parent":"blog2" # 指定父文檔的 id,表示子文檔屬於哪一個父文檔 } }
根據父文檔 id 來查詢父文檔,普通的查詢沒法查出子文檔的信息:
GET my_blogs/_doc/blog2
若是想查到子文檔的信息,須要使用 parent_id 查詢:
POST my_blogs/_search { "query": { "parent_id": { # parent_id 查詢 "type": "comment", # comment 表示是子文檔,便是表示想查詢子文檔信息 "id": "blog2" # 指定父文檔的 id } # 這樣能夠查詢到 blog2 的全部 comment } }
has_child 查詢能夠經過子文檔的信息,查到父文檔信息。
POST my_blogs/_search { "query": { "has_child": { # has_child 查詢 "type": "comment", # 指定子文檔類型,表示下面的 query 中的信息要在 comment 子文檔中匹配 "query" : { "match": {"username" : "Jack"} } # 在子文檔中匹配信息,最終返回全部的相關父文檔信息 } } }
has_parent 查詢能夠經過父文檔的信息,查到子文檔信息。
POST my_blogs/_search { "query": { "has_parent": { # has_parent 查詢 "parent_type": "blog", # 指定子文檔類型,表示下面的 query 中的信息要在 blog 父文檔中匹配 "query" : { "match": {"title" : "Learning Hadoop"} } # 在父文檔中匹配信息,最終返回全部的相關子文檔信息 } } }
普通的查詢沒法查到:
GET my_blogs/_doc/comment3
須要指定 routing 參數,提供父文檔 id:
GET my_blogs/_doc/comment3?routing=blog2
更新子文檔不會影響到父文檔。
示例:
# URI 中指定子文檔 id,並經過 routing 參數指定父文檔 id PUT my_blogs/_doc/comment3?routing=blog2 { "comment": "Hello Hadoop??", "blog_comments_relation": { "name": "comment", "parent": "blog2" } }
ES 中的動態 Mapping 指的是:
ES 類型的自動識別規則以下:
字段類型是否可以修改,分兩種狀況:
mappings._doc.dynamic
爲 ture
,當有新字段寫入時,Mappings
會自動更新。mappings._doc.dynamic
爲 false
,當有新字段寫入時,Mappings
不會更新;新增字段不會創建倒排索引,可是信息會出如今 _source
中。mappings._doc.dynamic
爲 strict
,當有新字段寫入時,寫入失敗。Reindex
重建索引。dynamic
有 3 種取值,使用下面 API 能夠修改 dynamic
的值:
PUT index_name/_mapping { "dynamic": false/true/strict }
經過下面語法能夠獲取一個索引的 Mapping:
GET index_name/_mapping
自定義 Mapping 的語法以下:
PUT index_name { "mappings" : { # 定義 } }
自定義 Mapping 的小技巧:
Mappings 有不少參數能夠設置,能夠參考這裏。
若是咱們要在 ES 中插入以下結構的數據:
PUT blog/_doc/1 { "content":"I like Elasticsearch", "time":"2019-01-01T00:00:00", "user": { # 是一個對象類型 "userid":1, "username":"Jack", "city":"Shanghai" } }
其中的 user 字段是一個對象類型。
這種結構的數據對應的 mappings 應該像下面這樣定義:
PUT /blog { "mappings": { "properties": { "content": { "type": "text" }, "time": { "type": "date" }, "user": { # user 內部又嵌套了一個 properties "properties": { "city": { "type": "text" }, "userid": { "type": "long" }, "username": { "type": "keyword" } } } } } }
若是咱們要在 ES 中插入以下結構的數據:
POST my_movies/_doc/1 { "title":"Speed", "actors":[ # actors 是一個數組類型,數組中的元素是對象類型 { "first_name":"Keanu", "last_name":"Reeves" }, { "first_name":"Dennis", "last_name":"Hopper" } ] }
其中的 actors 字段是一個數組類型,數組中的元素是對象類型。
像這種結構的數據對應的 mappings 應該像下面這樣定義:
PUT my_movies { "mappings": { "properties": { "actors": { # actors 字段 "properties": { # 嵌入了一個 properties "first_name": {"type": "keyword"}, "last_name": {"type": "keyword"} } }, "title": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } } } } }
能夠經過設置字段的 index 值,來控制某些字段是否可被搜索。
index
有兩種取值:true / false
,默認爲 true
。
當某個字段的 index
值爲 false
時,ES 就不會爲該字段創建倒排索引(節省空間),該字段也不能被搜索(若是搜索的話會報錯)。
設置語法以下:
PUT index_name { "mappings" : { # 固定寫法 "properties" : { # 固定寫法 "firstName" : { # 字段名 "type" : "text" }, "lastName" : { # 字段名 "type" : "text" }, "mobile" : { # 字段名 "type" : "text", "index": false # 設置爲 false } } } }
咱們能夠經過設置 index_options 的值來控制倒排索引項的內容,它有 4 種取值:
docs
:只記錄文檔 id
freqs
:記錄文檔 id
和 詞頻
positions
:記錄文檔 id
,詞頻
和 單詞 position
offsets
:記錄文檔 id
,詞頻
,單詞 position
和 字符 offset
Text
類型的數據,index_options
的值默認爲 positions
;其它
類型的數據,index_options
的值默認爲 docs
。
注意:對於 index_options 的默認值,不一樣版本的 ES,可能不同,請查看相應版本的文檔。
對於倒排索引項,其記錄的內容越多,佔用的空間也就越大,同時 ES 也會對字段進行更多的分析。
設置語法以下:
PUT index_name { "mappings": { # 固定寫法 "properties": { # 固定寫法 "text": { # 字段名 "type": "text", # 字段的數據類型 "index_options": "offsets" # index_options 值 } } } }
默認狀況下 null
和 空數組[]
是不可以被搜索的,好比下面的兩個文檔:
PUT my_index/_doc/1 { "status_code": null } PUT my_index/_doc/2 { "status_code": [] }
要想使得這兩個文檔可以被搜索,須要設置 null_value 參數,以下:
PUT my_index { "mappings": { "properties": { "status_code": { "type": "keyword", # 只有 Keyword 類型的數據,才支持設置 null_value "null_value": "NULL" # 將 null_value 設置爲 NULL,就能夠經過 NULL 搜索了 } } } }
注意只有 Keyword
類型的數據,才支持設置 null_value
,將 null_value
設置爲 NULL
,就能夠經過 NULL
搜索了,以下:
GET my-index/_search?q=status_code:NULL
索引模板(Index Template)設置一個規則,自動生成索引的 Mappings 和 Settings。
索引模板有如下特性:
多個模板時的 merge 規則,當一個索引被建立時:
對於相同字段的不一樣只會進行覆蓋,對於不一樣的字段會進行疊加依次使用。
索引模板示例:
PUT _template/template_1 # template_1 是自定義的索引模板的名稱 { "index_patterns": ["te*", "bar*"], # 匹配索引的規則,該模板會做用於這些索引名上 "settings": { # settings 設置 "number_of_shards": 1 }, "mappings": { # mappings 設置 "_source": { "enabled": false }, "properties": { "host_name": { "type": "keyword" }, "created_at": { "type": "date", "format": "EEE MMM dd HH:mm:ss Z yyyy" } } } }
多個索引模板:
PUT /_template/template_1 { "index_patterns" : ["*"], "order" : 0, "settings" : { "number_of_shards" : 1 }, "mappings" : { "_source" : { "enabled" : false } } } PUT /_template/template_2 { "index_patterns" : ["te*"], "order" : 1, "settings" : { "number_of_shards" : 1 }, "mappings" : { "_source" : { "enabled" : true } } }
動態模板(Dynamic Template)用於設置某個指定索引中的字段的數據類型。
(本節完。)
推薦閱讀:
歡迎關注做者公衆號,獲取更多技術乾貨。