小白學ES 12 - 什麼是Elasticsearch的動態對映 + 如何自定義動態對映
文章目錄
1 動態對映(dynamic mapping)
1.1 什麼是動態對映
沒有提前定義欄位和資料型別間的對映關係, 而是直接向ES中插入資料, 此時ES將根據每個field可能對應的資料型別, 自動為其配置type及其對應的mapping, 這個過程就是動態對映(dynamic mapping).
示例:
true or false --> boolean
233 --> long
123.45 --> double
2018-10-10 --> date
"hello world" --> string/text
可以配置自定義對映, 供ES在動態對映時使用.
- 動態對映雖然方便, 可並不直觀, 為了個性化自定義相關設定, 可以在新增文件之前, 先建立index和type, 並配置type對應的mapping, 以取代動態對映.
1.2 體驗動態對映
-
插入如下資料:
PUT website/blog/1 { "post_date": "2018-01-01", "title": "my first blog", "content": "my first blog in the website", "author_id": 5520 } PUT website/blog/2 { "post_date":
-
進行如下檢索測試:
GET website/blog/_search?q=2018 // 3條結果 GET website/blog/_search?q=2018-01-01 // 3條結果 GET website/blog/_search?q=post_date:2018-01-01 // 1條結果 GET website/blog/_search?q=post_date:2018 // 1條結果
-
檢視ES自動建立的mapping:
GET website/_mapping/blog // 結果如下: { "website": { "mappings": { "blog": { "properties": { "author_id": { "type": "long" }, "content": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }, "post_date": { "type": "date" // post_date為date型別 }, "title": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } } } } } } }
1.3 搜尋結果不一致的原因分析
上節中搜索結果不一致, 是因為ES自動建立mapping時, 為不同的field映射了不同的資料型別.
—— 不同資料型別在分詞、搜尋等行為上也是不同的.
(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型別, 所以將進行精確匹配.
-
post_date
欄位的倒排索引結果如下:注意: 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.2版本中做的一個優化, 搜尋01/02等是不會出現結果的, 搜尋2018會出現第一條結果.
2 開啟dynamic mapping策略
2.1 約束策略
(1) true: 開啟 —— 遇到陌生欄位時, 進行動態對映;
(2) false: 關閉 —— 遇到陌生欄位時, 忽略之;
(3) strict: 遇到陌生欄位時, 報錯處理.
2.2 策略示例
-
使用不同的約束策略:
PUT website { "mappings": { "user": { "dynamic": "strict", // 嚴格控制策略 "properties": { "name": { "type": "text" }, "address": { "type": "object", "dynamic": "true" // 開啟動態對映策略 } } } } }
-
插入資料演示:
// 插入資料時多新增一個欄位 PUT website/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 [user] is not allowed" } ], "type": "strict_dynamic_mapping_exception", "reason": "mapping set to strict, dynamic introduction of [content] within [user] is not allowed" }, "status": 400 } // 新增符合的資料, 操作成功: PUT website/user/1 { "name": "shou feng", "address": { "province": "guangdong", "city": "guangzhou" } }
-
檢視對映資訊:
GET website/_mapping/user // 對映資訊如下: { "website": { "mappings": { "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" } } } } } }
3 定製dynamic mapping策略
3.1 date_detection - 日期識別策略
ES預設按照一定的格式識別date型別的資料, 如"yyyy-MM-dd". 存在這種情況:
① 第一次新增文件時, 某個field是類似"2018-01-01"的值, 其型別就被動態對映成了date;
② 後期再次新增文件, 該field是類似"hello world"的值, ES就會因為型別不匹配而報錯.
為解決這一問題, 可以手動關閉某個type的date_detection, 如果有需要, 請指定某個field為date型別.
PUT website/_mapping/user
{
"date_detection": false
}
3.2 自定義動態對映模板 - type層面
-
在type中定義動態對映模板(dynamic mapping template):
PUT website { "mappings": { "user": { "dynamic_templates": [ { "en": { "match": "*_en", // 匹配"*_en"的field "match_mapping_type": "string", "mapping": { "type": "text", "analyzer": "english" // 使用english分詞器 } } } ] } } }
-
新增資料:
PUT website/user/1 { "name": "the first register user" } PUT website/user/2 { "name_en": "the second register user" }
-
檢索資料:
// 有結果: "name"沒有匹配到任何動態模板, 預設使用standard分詞器 GET website/user/_search { "query": { "match": {"name": "the"} } } // 無結果: "name_en"匹配到了動態模板, 使用english分詞器, the是停用詞, 被過濾掉了 GET website/user/_search { "query": { "match": {"name_en": "the"} } }
-
注意:
這裡的
match_mapping_type
的型別支援[object, string, long, double, boolean, date, binary]
, 若使用text
將丟擲如下警告資訊: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]
3.3 自定義預設對映模板 - index級別
-
在index中定義預設對映模板(default mapping template):
PUT website { "mappings": { "_default_": { "_all": { "enabled": false } }, "blog": { "_all": { "enabled": true } } } }
-
預設對映模板的使用:
個人理解: 預設對映模板應該是類似於全域性變數的存在, 對當前配置的索引起作用.
具體使用: 尚未嘗試, 後續接觸到時再補充此部分內容.
版權宣告
作者: ma_shoufeng(馬瘦風)
出處: CSDN 馬瘦風的部落格
您的支援是對博主的極大鼓勵, 感謝您的閱讀.
本文版權歸博主所有, 歡迎轉載, 但未經博主同意必須保留此段宣告, 且在文章頁面明顯位置給出原文連結, 否則博主保留追究相關人員法律責任的權利.