自動映射是ES提供的一個重要的特性,它將文檔建立索引之前的工作全部自動化了(創建索引、定義映射類型、字段發現/定義字段);
可以通過以下方式自定義動態映射規則
1、字段動態映射:管理字段動態發現
默認情況下文檔中新增了字段,es能自動發現變化並添加新字段到索引當中,這個特性可以通過設置dynamic參數爲false(忽略新字段)或strict(拋異常)來禁止;
假設dynamic參數映射爲true,以下簡單規則用於確定新增字段的類型:
序號 | json數據類型 | ES數據類型 |
---|---|---|
1 | null | 沒有字段添加 |
2 | true或false | boolean字段 |
3 | 浮點數 | float字段 |
4 | integer | long字段 |
5 | object | object字段 |
6 | array | 取決於數組第一個非空值的類型 |
7 | string | date/double/long/text(新增一個keyword的子級字段)類型中匹配的一個 |
這些規則僅適用於字段數據類型,其他的類型(複雜類型、geo類型、特殊類型等)必須要顯式指定;
日期檢測
若date_detection參數啓用(默認啓用),當新增加的字段內容能夠匹配dynamic_date_formates則認定該字段類型爲date類型;
dynamic_date_formates默認格式:[“strict_date_optional_time”,“yyyy/MM/dd HH:mm:ss Z||yyyy/MM/dd Z”]
PUT dyn_date_detection_1_index/_doc/1
{
"create_time":"2020/05/31"
}
GET dyn_date_detection_1_index/_mapping
{
"dyn_date_detection_1_index" : {
"mappings" : {
"properties" : {
"create_time" : {
"type" : "date",
"format" : "yyyy/MM/dd HH:mm:ss||yyyy/MM/dd||epoch_millis"
}
}
}
}
}
禁用日期自動檢測
PUT dyn_date_detection_2_index
{
"mappings": {
"date_detection": false
}
}
PUT dyn_date_detection_2_index/_doc/1
{
"create_time":"2020/05/31"
}
//create_time類型被映射爲text
GET dyn_date_detection_2_index/_mapping
{
"dyn_date_detection_2_index" : {
"mappings" : {
"date_detection" : false,
"properties" : {
"create_time" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
}
}
數值類型自動檢測
因爲json支持原生浮點數和整數數據類型,一些應用或編程語言可能會將數值渲染爲字符串;通常正確的解決方案是顯式映射這些字段,不過啓用數字檢測(默認爲禁用狀態)可以自動執行此操作:
PUT dyn_numeric_detection_index
{
"mappings": {
"numeric_detection": true
}
}
PUT dyn_numeric_detection_index/_doc/1
{
"float_define":"1.0",
"integer_define":"1"
}
GET dyn_numeric_detection_index/_mapping
2、動態映射模板:配置新增字段的映射規則
動態模板允許自定義映射規則:
1)、ES結合match_mapping_type自動檢測數據類型;
2)、根據字段名稱使用match、unmatch或者match_pattern進行匹配;
3)、根據字段全限定路徑使用path_match和path_unmatch進行匹配;
原始字段名可使用模板變量{name}代替,檢測到的數據類型可使用模板變量{dynamic_type}代替;
動態映射的字段要求新增的字段有確定的值(null或空數組不滿足),這也就意味着如果在動態模板字段中設置了null_value參數,該參數要在配置該參數字段首次有確定值的時被應用;
動態模板映射模板格式:
"dynamic_templates": [
{
//模板名稱可以自定義
"my_template_name": {
//match conditions可包含的類型:match_maooing_type,match,match_pattern,unmatch,path_match,path_unmatch
... match conditions ...
//匹配的字段應該映射的類型
"mapping": { ... }
}
}
]
若模板代碼段中包含不合法的表達,則在校驗時會導致校驗失敗的錯誤,校驗的操作會在模板應用於索引時或是模板更新時;
模板的執行將按照代碼順序執行,若字段類型匹配則不會執行其他規則的匹配,當模板代碼被更新時,已存在的模板會被重寫,這允許初始化之後的模板能夠被重新排序或刪除;
match_mapping_type參數
match_mapping_type對應的值是json解析器檢測到的數據類型,因爲json無法區分long與integer類型或doubble與float類型,故而選擇較寬的數據類型,即整數會表示爲long,浮點數表示爲doubble;
以下的數據類型會被自動監測:
序號 | 類型 | 可能值 |
---|---|---|
1 | boolean | true/false |
2 | date | 日期自動檢查發現string字段與日期格式匹配 |
3 | double | 帶小數的數字 |
4 | long | 不帶小數的數字 |
5 | object | 對象 |
6 | string | 字符串類型 |
爲了能夠匹配所有的數據類型,可以將所有的整數映射成long,所有的字符串類型映射成text和keyword
PUT dyn_all_datatype_match_index
{
"mappings": {
"dynamic_templates": [
{
"integers": {
"match_mapping_type": "long",
"mapping": {
"type": "integer"
}
}
},
{
"strings": {
"match_mapping_type": "string",
"mapping": {
"type": "text",
"fields": {
"raw": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
]
}
}
//age字段映射成integer,desc字段映射成text且子級字段映射成keyword
PUT dyn_all_datatype_match_index/_doc/1
{
"age":5,
"desc":"she is a nice girl"
}
match與unmatch參數
match參數使用模式匹配來匹配字段名,unmatch參數使用模式匹配來排除匹配的字段名;
以下示例演示了所有string類型字段名匹配以long_開始的字段並且排除以_text結果的字段,並將滿足條件的字段映射成long類型:
PUT dyn_param_match_index
{
"mappings": {
"dynamic_templates": [
{
"long_as_strings": {
"match_mapping_type": "string",
"match": "long_*",
"unmatch": "*_text",
"mapping": {
"type": "long"
}
}
}
]
}
}
//long_num匹配規則'long_*'將映射成long類型,long_text因匹配'*_text'將無法映射成long,轉而使用默認的映射規則
PUT dyn_param_match_index/_doc/1
{
"long_num":"5",
"long_text":"it's a long text"
}
查看映射詳情
GET dyn_param_match_index/_mapping
結果返回
{
"dyn_param_match_index" : {
"mappings" : {
"dynamic_templates" : [
{
"long_as_strings" : {
"match" : "long_*",
"unmatch" : "*_text",
"match_mapping_type" : "string",
"mapping" : {
"type" : "long"
}
}
}
],
"properties" : {
"long_num" : {
"type" : "long"
},
"long_text" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
}
}
match_pattern參數
match_pattern參數用於調整match參數的行爲,其支持java正則匹配表達式
PUT dyn_template_regex_index
{
"mappings": {
"dynamic_templates": [
{
"profit_adapt": {
"match_pattern": "regex",
"match": """^total_orders_\d+$""",
"unmatch": """^total_orders_*_text$""",
"mapping": {
"type": "long"
}
}
}
]
}
}
PUT dyn_template_regex_index/_doc/1
{
"total_orders_202004":"1254",
"total_orders_202005":"1665",
"total_orders_202005_text":"1665"
}
GET dyn_template_regex_index/_mapping
{
"dyn_template_regex_index" : {
"mappings" : {
"dynamic_templates" : [
{
"profit_adapt" : {
"match" : """^total_orders_\d+$""",
"unmatch" : "^total_orders_*_text$",
"match_pattern" : "regex",
"mapping" : {
"type" : "long"
}
}
}
],
"properties" : {
"total_orders_202004" : {
"type" : "long"
},
"total_orders_202005" : {
"type" : "long"
},
"total_orders_202005_text" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
}
}
path_match與path_unmatch參數
path_match/path_unmatch參數工作方式與match/unmatch參數工作方式一樣,不過前者需要指定字段路徑,而不僅僅是字段名稱,例如some_object.*.some_field:
//以下template限定路徑匹配以'name'開頭且排除以'middle'結尾的字段,定義其類型爲text,並將字段值拷貝到'full_name'字段上,排除的字段將按照默認映射規則處理
PUT dyn_template_path_match_index
{
"mappings": {
"dynamic_templates": [
{
"full_name": {
"path_match": "name.*",
"path_unmatch": "*.middle",
"mapping": {
"type": "text",
"copy_to": "full_name"
}
}
}
]
}
}
//此處name.first與name.last將命中規則,name.middle將使用默認映射規則處理
PUT dyn_template_path_match_index/_doc/1
{
"name":{
"first":"Jack",
"middle":"Black",
"last":"Rose"
}
}
需要注意的是path_match/path_unmatch參數匹配需要指定到葉子節點的字段,反之若匹配的爲非葉子節點將會報錯:
//報錯,因爲name,title獲取到的是object而非string,錯誤信息:Can't get text on a START_OBJECT at 5:13
PUT dyn_template_path_match_index/_doc/2
{
"name":{
"first":"Paul",
"last":"Mike",
"title":{
"value":"es",
"category":"distribute too of software"
}
}
}
佔位符{name}與{dynamic_type}
{name}與{dynamic_type}佔位符分別代表了在映射時映射字段的名稱及檢測的字段類型
//'named_analyzer’指定analyzer爲映射字段名,而’no_doc_values’則指定字段自動的映射類型爲其type
PUT dyn_template_placeholder_index
{
"mappings": {
"dynamic_templates": [
{
"named_analyzer": {
"match_mapping_type": "string",
"match": "*",
"mapping": {
"type": "text",
"analyzer": "{name}"
}
}
},
{
"no_doc_values": {
"match_mapping_type": "*",
"mapping": {
"type": "{dynamic_type}",
"doc_values": false
}
}
}
]
}
}
//此處指定字段english的analyzer爲english,count字段自動映射,其類型爲long
PUT dyn_template_placeholder_index/_doc/1
{
"english":"some english text",
"count":5
}
模板實例
1)、結構化查詢
默認情況下es映射string類型字段會處理爲text類型且其子字段類型爲keyword,若只想建立結構化索引且不需要全文索引,可以將es中所有字段的類型映射爲keyword類型,這也就意味着查詢這些字段需要精確指定查詢值:
PUT dyn_structure_search_index
{
"mappings": {
"dynamic_templates": [
{
"string_as_keyword": {
"match_mapping_type": "string",
"mapping": {
"type": "keyword"
}
}
}
]
}
}
2)、string類型字段全部以text進行映射
與前例相反,若只需要全文索引而不考慮排序、聚合或精確查找,可以將所有string類型字段映射爲text類型:
PUT dyn_text_only_index
{
"mappings": {
"dynamic_templates": [
{
"string_as_text": {
"match_mapping_type": "string",
"mapping": {
"type": "text"
}
}
}
]
}
}
3)、禁用norms參數
norms參數影響索引時分數計算,若不會使用文檔相關分來進行排序則可以禁用該參數以節約一些存儲空間:
PUT dyn_disable_norms_index
{
"mappings": {
"dynamic_templates": [
{
"string_as_keywords": {
"match_mapping_type": "string",
"mapping": {
"type": "text",
"norms": false,
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
]
}
}
4)、時間序列
使用es針對時間序列進行分析時,通常有很多的數值字段且經常對這些字段進行聚合操作而根本不用過濾操作,這種情況下可以禁止爲這些字段建立索引以節省磁盤空間以及提升索引的速度:
PUT dyn_time_series_index
{
"mappings": {
"dynamic_templates": [
{
"unindexed_longs": {
"match_mapping_type": "long",
"mapping": {
"type": "long",
"index": false
}
}
},
{
"unindexed_doubles": {
"match_mapping_type": "double",
"mapping": {
"type": "double",
"index": false
}
}
}
]
}
}