目錄html
動態映射時Elasticsearch的一個重要特性: 不須要提早建立iindex、定義mapping信息和type類型, 你能夠 直接向ES中插入文檔數據時, ES會根據每一個新field可能的數據類型, 自動爲其配置type等mapping信息, 這個過程就是動態映射(dynamic mapping).web
Elasticsearch動態映射的示例:shell
字段內容(field) | 映射的字段類型(type) |
---|---|
true | false | boolean |
1234 | long |
123.4 | float |
2018-10-10 | date |
"hello world" | text |
說明: 動態映射雖然方便, 可並不直觀, 爲了個性化自定義相關設置, 能夠在添加文檔以前, 先建立index和type, 並配置type對應的mapping, 以取代動態映射.
mapping的配置可參考博文: ES 11 - 配置Elasticsearch的映射(mapping).json
(1) 插入以下數據:bash
若是已有website索引, 先刪除再執行下面的插入操做:
DELETE website
.app
PUT website/blog/1 { "blog_id": 10001, "author_id": 5520, "post_date": "2018-01-01", "title": "my first blog", "content": "my first blog in the website" } PUT website/blog/2 { "blog_id": 10002, "author_id": 5520, "post_date": "2018-01-02", "title": "my second blog", "content": "my second blog in the website" } PUT website/blog/3 { "blog_id": 10003, "author_id": 5520, "post_date": "2018-01-03", "title": "my third blog", "content": "my third blog in the website" }
(2) 進行以下檢索測試:elasticsearch
注意這裏結果數是3的狀況.ide
GET website/blog/_search?q=2018 // 1條結果, 5.6以前的版本是3條結果 GET website/blog/_search?q=2018-01-01 // 1條結果, 5.6以前的版本是3條結果 GET website/blog/_search?q=post_date:2018 // 1條結果 GET website/blog/_search?q=post_date:2018-01-01 // 1條結果
(3) 查看ES自動創建的mapping:post
GET website/_mapping // 結果以下: { "website" : { // index是website "mappings" : { "blog" : { // type是blog "properties" : { "author_id" : { "type" : "long" }, "blog_id" : { "type" : "long" }, "content" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } }, "post_date" : { "type" : "date" // 發佈日期"2018-01-01"被自動識別爲date類型 }, "title" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } } } } } } }
若是使用的是較早的版本, 以5.6.x爲例, [1.2]節中搜索結果會不一致, 這是由於:測試
ES自動創建mapping時, 爲不一樣的field映射了不一樣的數據類型, 而不一樣數據類型在分詞、搜索等行爲上也是不一樣的.
官方文檔指出, 從6.0+版本開始,
_all
字段的設置已經禁止使用, 建議咱們使用copy_to
實現類似的功能.—— 也就是說, 若是_all
字段被關閉, 就不會出現搜索結果不一致的狀況.
(1) GET website/blog/_search?q=2018
ES默認將每一個文檔的全部field的值抽取到一個名爲
_all
的元字段中, 如id=1的文檔的_all
的值爲:2018-01-01 my first blog my first blog in the website 5520說明:
_all
字段將全部的值做爲字符串索引, 因此日期被索引爲年、月、日三個值,_all
字段的倒排索引結果以下:
doc1 doc2 Doc3 2018 * * * 01 * * * 02 * 03 * 此項搜索中, ES是從
_all
字段中檢索, 3個文檔中都有2018
, 因此結果數是3.
(2) GET website/blog/?q=2018-01-01
同(1), ES也是從
_all
字段中檢索, 結果數一樣是3.
(3) GET website/blog/_search?q=post_date:2018-01-01
此檢索指定了檢索條件, ES將從post_date字段中檢索, 而post_date被映射爲date類型, 因此將進行精確匹配.
而date類型的字段索引的內容有其默認的固定格式.
post_date
字段的倒排索引結果以下:
doc1 doc2 doc3 2018-01-01 00:00:00 UTC * 2018-01-02 00:00:00 UTC * 2018-01-03 00:00:00 UTC * 能夠看出, 知足條件的只有1個結果, 即doc1.
(4) GET /_search?q=post_date:2018
這是ES 5.x版本中作的一個優化, 搜索
post_date:01
等是不會出現結果的, 搜索2018會出現第一條結果.
策略 | 功能說明 |
---|---|
true |
開啓 —— 遇到陌生字段時, 進行動態映射 |
false |
關閉 —— 忽略遇到的陌生字段 |
strict |
遇到陌生字段時, 做報錯處理 |
(1) 使用不一樣的約束策略:
PUT user { "mappings": { "blog_user": { "dynamic": "strict", // 嚴格控制策略 "properties": { "name": { "type": "text" }, "address": { "type": "object", "dynamic": "true" // 開啓動態映射策略 } } } } }
(2) 插入數據演示:
// 插入數據時多添加一個字段 PUT user/blog_user/1 { "name": "shou feng", "content": "this is my blog", // 多添加的字段 "address": { "province": "guangdong", // 多添加的字段 "city": "guangzhou" // 多添加的字段 } }
將拋出以下錯誤信息:
{ "error": { "root_cause": [ { "type": "strict_dynamic_mapping_exception", // 錯誤緣由: 不容許動態添加field "reason": "mapping set to strict, dynamic introduction of [content] within [blog_user] is not allowed" } ], "type": "strict_dynamic_mapping_exception", "reason": "mapping set to strict, dynamic introduction of [content] within [blog_user] is not allowed" }, "status": 400 }
添加符合約束的數據, 操做就能成功:
PUT user/blog_user/1 { "name": "shou feng", "address": { "province": "guangdong", "city": "guangzhou" } }
(3) 查看映射信息:
GET user/_mapping // 映射信息以下: { "user" : { "mappings" : { "blog_user" : { "dynamic" : "strict", // 嚴格約束條件 "properties" : { "address" : { "dynamic" : "true", // 開啓動態映射策略 "properties" : { "city" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } }, "province" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } } } }, "name" : { "type" : "text" } } } } } }
對於date類型的數據, Elasticsearch有其默認的識別策略, 好比"yyyy-MM-dd". 存在這種狀況:
① 第一次添加文檔時, 某個field是相似"2018-01-01"的值, 其類型就被動態映射成了date;
② 後期再次添加文檔, 該field是相似"hello world"的值, ES就會由於類型不匹配而報錯.
爲解決這一問題, 能夠手動關閉某個type的date_detection; 若是不須要關閉, 建議手動指定這個field爲date類型.
關閉示例以下:
PUT user/_mapping/blog_user { "date_detection": false }
(1) 在type中定義動態映射模板(dynamic mapping template) —— 把全部的string類型映射成text和keyword類型:
先刪除已有的
user
索引:DELETE user
, 再執行下述命令:
PUT user { "mappings": { "blog_user": { "dynamic_templates": [ { "en": { "match": "*_en", // 匹配"*_en"的field "match_mapping_type": "string", "mapping": { "type": "text", // 把全部的string類型, 映射成text類型 "analyzer": "english", // 使用english分詞器 "fields": { "raw": { "type": "keyword", "ignore_above": 256 } } } } } ] } } }
(2) 添加數據:
PUT user/blog_user/1 { "name": "the first register user" } PUT user/blog_user/2 { "name_en": "the second register user" }
(3) 檢索數據:
// 有結果: "name"沒有匹配到任何動態模板, 默認使用standard分詞器 GET user/_search { "query": { "match": {"name": "the"} } } // 無結果: "name_en"匹配到了動態模板, 使用english分詞器, the是停用詞, 被過濾掉了 GET user/_search { "query": { "match": {"name_en": "the"} } }
說明:
這裏的
match_mapping_type
的類型支持[object, string, long, double, boolean, date, binary]
, 若使用text
將拋出以下錯誤信息:{ "error": { "root_cause": [ { "type": "mapper_parsing_exception", "reason": "Failed to parse mapping [blog_user]: No field type matched on [text], possible values are [object, string, long, double, boolean, date, binary]" } ], "type": "mapper_parsing_exception", "reason": "Failed to parse mapping [blog_user]: No field type matched on [text], possible values are [object, string, long, double, boolean, date, binary]", "caused_by": { "type": "illegal_argument_exception", "reason": "No field type matched on [text], possible values are [object, string, long, double, boolean, date, binary]" } }, "status": 400 }在6.0以前的版本, 將拋出以下過時的警告信息:
Deprecation: match_mapping_type [text] is invalid and will be ignored: No field type matched on [text], possible values are [object, string, long, double, boolean, date, binary]
_default mapping
- 默認映射模板是相似於全局變量的存在, 對當前配置的索引發做用.
默認映射模板在Elasticsearch 6.x版本中已經再也不支持, 由於6.0版本開始, 每一個索引只能有一個類型, 所以默認模板沒有存在的意義了.
下面的演示過程, 是在6.0以前的版本上的測試.
(1) 在index中定義默認映射模板(default mapping template):
先刪除已有的
user
索引:DELETE user
, 再執行下述命令:
PUT user { "mappings": { "_default_": { "_all": { "enabled": false } }, "blog_user": { "_all": { "enabled": true } } } }
(2) 動態映射能夠與索引模板(Index Templates)配合使用.
不管是自動建立Index, 仍是手動顯示建立Index, 索引模板均可以用來配置新索引的默認mappings(映射), settings(配置項)和aliases(別名). 具體使用方法請參考博客: ES 10 - Elasticsearch的索引別名和索引模板
參考資料
版權聲明
做者: 馬瘦風
出處: 博客園 馬瘦風的博客
您的支持是對博主的極大鼓勵, 感謝您的閱讀.
本文版權歸博主全部, 歡迎轉載, 但請保留此段聲明, 並在文章頁面明顯位置給出原文連接, 不然博主保留追究相關人員法律責任的權利.