1. 介紹
動態(tài)映射(Dynamic Mapping)是指當(dāng)Elasticsearch遇到文檔中之前未遇到的字段偶宫,會自動檢測及確定字段的數(shù)據(jù)類型并自動把新字段的類型添加到映射中的過程躯畴。
舉個例子:
PUT my_index/_doc/1
{ "count": 5 }
執(zhí)行上面的PUT調(diào)用批钠,Elasticsearch會創(chuàng)建一個my_index索引刨疼,包含名字為count的字段悉默,字段數(shù)據(jù)類型為long间螟,并自動把新的字段類型添加到映射中纤垂,索引my_index的mapping信息如下所示:
GET my_index/_mappings
{}
# 返回的mapping信息
{
"my_index" : {
"mappings" : {
"properties" : {
"count" : {
"type" : "long"
}
}
}
}
}
動態(tài)參數(shù)設(shè)置
通過設(shè)置參數(shù)dynamic夕晓,可以在文檔和對象級別控制動態(tài)映射的這種行為宛乃,參數(shù)dynamic可以設(shè)置為下列三種值:
(1)true:將新的檢測到的字段添加到映射中。(默認(rèn))
(2)false:忽略新檢測到的字段。這些字段將不會被索引征炼,因此不能被搜索析既,但仍然會出現(xiàn)在返回命中的_source字段中。這些字段將不會添加到映射中谆奥,新的字段必須顯式添加眼坏。
(3)strict:如果檢測到新字段,則拋出異常并拒絕索引文檔酸些。新字段必須顯式地添加到映射中宰译。
- 操作示例如下:
# 1 - dynamic設(shè)置為strict,并且是類型級別魄懂,表示不會動態(tài)添加top級字段
# 2 - user 對象繼承類型級別設(shè)置
# 3 - dynamic設(shè)置為true沿侈,并且是對象級別,表示social_networks對象可以動態(tài)添加字段
PUT my_index
{
"mappings": {
"dynamic": "strict", // 1
"properties": {
"user": { // 2
"properties": {
"social_networks": {
"dynamic": "true", // 3
"properties": {}
}
}
}
}
}
}
如果啟用了動態(tài)字段映射市栗,Elasticsearch采用一些規(guī)則來確定JSON字段對應(yīng)的數(shù)據(jù)類型缀拭,規(guī)則包括動態(tài)字段映射(Dynamic field mappings)和動態(tài)模板集(Dynamic templates)。
2. 動態(tài)字段映射
動態(tài)字段映射(Dynamic field mappings):動態(tài)字段的檢測映射規(guī)則肃廓。
動態(tài)字段映射規(guī)則
JSON數(shù)據(jù)類型 | Elasticsearch數(shù)據(jù)類型 |
---|---|
null | 無字段添加 |
true或false | boolean類型 |
浮點數(shù) | float類型 |
整數(shù) | long類型 |
對象 | object類型 |
數(shù)組 | 取決于數(shù)組中第一個非空值 |
字符串 | date類型(日期檢測)智厌、double類型诲泌、 long類型(數(shù)字檢測)盲赊、text類型、 keyword 類型 |
只有上面這些數(shù)據(jù)類型會被動態(tài)檢測敷扫,所有其他數(shù)據(jù)類型必須顯式地映射哀蘑。
日期檢測
如果啟用了date_detection(默認(rèn)啟用),那么將檢查新的字符串字段葵第,看它們的內(nèi)容是否匹配dynamic_date_formats中指定的任何日期模式绘迁。如果找到匹配項,將添加相應(yīng)格式的一個新日期字段卒密。
- 參數(shù)dynamic_date_formats 默認(rèn)格式為
[ "strict_date_optional_time","yyyy/MM/dd HH:mm:ss Z||yyyy/MM/dd Z"]
舉個例子:
# 創(chuàng)建索引缀台,未指定字段類型
PUT my_index_01/_doc/1
{"create_date":"2015/09/02"}
# 查看索引的映射
GET my_index_01/_mapping
# 返回結(jié)果,表示已經(jīng)動態(tài)映射為日期類型
{
"my_index_01" : {
"mappings" : {
"properties" : {
"create_date" : {
"type" : "date",
"format" : "yyyy/MM/dd HH:mm:ss||yyyy/MM/dd||epoch_millis"
}
}
}
}
}
禁用日期檢測
如果禁用了日期檢測哮奇,那么Elasticsearch遇到日期格式的字符串膛腐,會動態(tài)映射到其他類型(text或keyword),通過設(shè)置參數(shù)date_detection等于false來禁用動態(tài)日期檢測鼎俘。示例如下:
# 禁用date_detection
PUT my_index_01
{"mappings":{"date_detection":false}}
# 創(chuàng)建索引哲身,未指定字段類型
PUT my_index_01/_doc/1
{"create_date":"2015/09/02"}
# 查看索引的映射
GET my_index_01/_mapping
# 返回結(jié)果,表示已經(jīng)動態(tài)映射為text類型
{
"my_index_01" : {
"mappings" : {
"date_detection" : false,
"properties" : {
"create_date" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
}
}
自定義檢測日期格式
可以自定義動態(tài)檢測的日期格式贸伐。示例如下:
PUT my_index_01
{"mappings":{"dynamic_date_formats":["MM/dd/yyyy"]}}
數(shù)字檢測
雖然JSON支持本地浮點數(shù)和整數(shù)數(shù)據(jù)類型勘天,但一些應(yīng)用程序或語言有時可能將數(shù)字呈現(xiàn)為字符串。通常正確的解決方案是顯式映射這些字段,但數(shù)字檢測(默認(rèn)禁用)可以自動做到這一點脯丝,示例如下:
# 開啟數(shù)字檢測
PUT my_index_01
{"mappings":{"numeric_detection":true}}
PUT my_index_01/_doc/1
{"my_float":"1.0","my_integer":"1"}
GET my_index_01/_mapping
{}
# 返回結(jié)果商膊,字段 my_float 映射為float類型,字段 my_integer 映射為long類型
{
"my_index_01" : {
"mappings" : {
"numeric_detection" : true,
"properties" : {
"my_float" : {
"type" : "float"
},
"my_integer" : {
"type" : "long"
}
}
}
}
}
3. 動態(tài)模板集
動態(tài)模板集(Dynamic templates):用于自定義規(guī)則來為動態(tài)添加的字段配置映射巾钉。
動態(tài)模板集是一個命名object類型的數(shù)組翘狱,包含至少一個動態(tài)模板,結(jié)構(gòu)示例如下:
# 雙斜線在執(zhí)行時需要去掉
PUT my_index_01
{
"mappings": {
"dynamic_templates": [ //1
{
"integers": { // 2
"match_mapping_type": "long", //3
"mapping": { // 4
"type": "integer"
}
}
}
]
}
}
- 注釋1-動態(tài)模板集參數(shù)名為dynamic_templates砰苍,數(shù)據(jù)類型是支持object的數(shù)組潦匈。
- 注釋2-動態(tài)模板名稱自定義。
- 注釋3-匹配條件赚导,包括
match_mapping_type, match, match_pattern, unmatch, path_match, path_unmatch
茬缩。 - 注釋4-匹配字段使用的類型映射。
動態(tài)模板集包含幾類重要參數(shù):
(1)match_mapping_type作用于檢測數(shù)據(jù)類型吼旧。
(2)match和unmatch或match_pattern作用于字段的名稱凰锡。
(3)path_match和path_unmatch作用于字段的完整點路徑。
可以在動態(tài)模板集中的映射使用占位符{name}和{dynamic_type}圈暗, {name}表示原始字段名掂为,{dynamic_type}表示檢測到的數(shù)據(jù)類型。
驗證動態(tài)模板集
在建立索引應(yīng)用動態(tài)模板集或更新動態(tài)模板集時员串,Elasticsearch會對動態(tài)模板集的映射片段進(jìn)行驗證勇哗,驗證流程如下:
如果在映射片段中使用了{(lán)name}占位符,則在更新動態(tài)模板集時跳過驗證寸齐,這是因為更新時字段名是未知的欲诺。但是在建立索引時應(yīng)用模板時會進(jìn)行驗證。
處理動態(tài)模板集
- 如果動態(tài)模板集中存在多個模板時渺鹦,會按照順序處理模板扰法,第一個匹配的模板將會使用。
- 當(dāng)通過put mapping API放置新的動態(tài)模板集時毅厚,所有現(xiàn)有的模板都會被覆蓋塞颁。并且允許動態(tài)模板集在添加后被重新排序或刪除。
match_mapping_type
- match_mapping_type對應(yīng)的值是JSON解析器檢測到的數(shù)據(jù)類型吸耿。因為JSON不區(qū)分long和integer或者double和float祠锣,所以它總是選擇更寬的數(shù)據(jù)類型,比如long表示整數(shù)珍语,double表示浮點數(shù)锤岸。
- match_mapping_type數(shù)據(jù)類型有下列幾種會被自動檢測到:
- 當(dāng)值為true或false時,類型為boolean板乙。
- 當(dāng)啟用日期檢測并找到與任何配置的日期格式匹配的字符串值時是偷,類型為date拳氢。
- 當(dāng)值有小數(shù)部分的數(shù)字,類型為double蛋铆。
- 當(dāng)值沒有小數(shù)部分的數(shù)字馋评,類型為long。
- 當(dāng)值為對象或散列結(jié)構(gòu)時刺啦,類型為object留特。
- 當(dāng)值為字符串時,類型為string玛瘸。
此外蜕青,符號*可以用于匹配所有數(shù)據(jù)類型。
例如糊渊,將所有整數(shù)字段映射為integer類型而不是long類型右核,將所有字符串字段映射為text類型和keyword類型,可使用以下模板:
PUT my_index_01
{
"mappings": {
"dynamic_templates": [
{
"template1": {
"match_mapping_type": "long",
"mapping": {
"type": "integer"
}
}
},
{
"template2": {
"match_mapping_type": "string",
"mapping": {
"type": "text",
"fields": {
"raw": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
]
}
}
PUT my_index_01/_doc/1
{"my_integer":5,"my_string":"Some string"}
match和unmatch
- match參數(shù)使用模式對字段名進(jìn)行匹配渺绒,而unmatch使用模式來排除通過match匹配的字段贺喝。
例如,匹配所有字段名稱以long_開頭的字符串字段(排除以_text結(jié)尾的)宗兼,并將它們映射為long字段躏鱼,可使用以下模板:
PUT my_index_01
{
"mappings": {
"dynamic_templates": [
{
"longs_as_strings": {
"match_mapping_type": "string",
"match": "long_*",
"unmatch": "*_text",
"mapping": {
"type": "long"
}
}
}
]
}
}
PUT my_index_01/_doc/1
{"long_num":"5","long_text":"foo"}
match_pattern
- match_pattern參數(shù)用來調(diào)整match參數(shù)的行為,可以在字段名上支持完整的Java正則表達(dá)式匹配殷绍,例如:
PUT my_index_01
{
"mappings": {
"dynamic_templates": [
{
"pattern_as_strings": {
"match_mapping_type": "string",
"match_pattern": "regex",
"match": "^long_\\d+$",
"mapping": {
"type": "long"
}
}
}
]
}
}
# 字段long_1映射為long類型染苛,字段long_text映射為text或keyword類型
PUT my_index_01/_doc/1
{"long_1":"5","long_text":"foo"}
path_match和path_unmatch
- path_match和path_unmatch參數(shù)的工作方式與match和unmatch相同,但操作在字段的完整點路徑上篡帕,而不僅僅是字段名稱殖侵。
例如:
PUT my_index_01
{
"mappings": {
"dynamic_templates": [
{
"full_name": {
"path_match": "name.*",
"path_unmatch": "*.middle",
"mapping": {
"type": "text",
"copy_to": "full_name"
}
}
}
]
}
}
PUT my_index_01/_doc/1
{"name":{"first":"John","middle":"Winston","last":"Lennon"}}
上面例子將字段名為name的對象中所有子級字段(排除子級middle字段)的值復(fù)制到頂層的full_name字段贸呢,創(chuàng)建新的字段full_name镰烧,復(fù)制內(nèi)容到full_name字段中,但是不會影響_source字段內(nèi)容楞陷。
{name}和{dynamic_type}
占位符{name}被替換為字段名怔鳖,占位符{dynamic_type}被替換為檢測到的動態(tài)字段類型。
例如固蛾,將所有字符串字段設(shè)置為使用與字段同名的分析器结执,并對所有非字符串字段禁用doc_values,可使用以下模板:
PUT my_index_01
{
"mappings": {
"dynamic_templates": [
{
"named_analyzers": {
"match_mapping_type": "string",
"match": "*",
"mapping": {
"type": "text",
"analyzer": "{name}"
}
}
},
{
"no_doc_values": {
"match_mapping_type": "*",
"mapping": {
"type": "{dynamic_type}",
"doc_values": false
}
}
}
]
}
}
# english字段被映射為english分析器的text類型字段艾凯。
# count字段被映射為禁用doc_values的long類型字段献幔。
PUT my_index_01/_doc/1
{"english":"Some English text","count":5}
4. 結(jié)語
Elasticsearch的動態(tài)映射功能已完成了基本介紹,后續(xù)在應(yīng)用環(huán)境中需要根據(jù)實際情況靈活運(yùn)用趾诗。