ElasticSearch笔记-动态映射
介绍
当Elasticsearch在文档中检测到新字段时,会自动确定字段的数据类型,并自动把新字段添加到映射的过程称为动态映射。
如果启用了动态字段映射,Elasticsearch采用一些规则来确定JSON字段对应的数据类型,规则包括动态字段映射(Dynamic field mappings)和动态模板集(Dynamic templates)。
动态参数设置(dynamic)
通过设置参数dynamic,可以在文档和对象级别控制动态映射的行为,dynamic可以有下列三种值:
true:将检测到的新字段自动添加到映射中(默认)
false:忽略检测到的新字段。这些字段不会被索引,因此不能搜索,但仍然会出现在_source字段中。这些字段将不会添加到映射中,新字段必须显式添加
strict:如果检测到新字段,抛出异常。新字段必须显式添加
dynamic设置为strict,并且是类型级别,表示不会动态添加top级字段
user 对象继承类型级别设置
dynamic设置为true,并且是对象级别,表示social_networks对象可以动态添加字段
PUT my_index
{
"mappings": {
"dynamic": "strict", // 1
"properties": {
"user": { // 2
"properties": {
"social_networks": {
"dynamic": "true", // 3
"properties": {}
}
}
}
}
}
}
动态字段映射规则
JSON数据类型 | ES数据类型 |
---|---|
true 或 false | boolean类型 |
浮点型数字 | double |
整型数字 | long |
JSON对象 | Object |
数组 | 第一个非空值得类型 |
String | 1、如果满足日期类型的格式,映射为日期类型(date) |
2、如果满足数字型的格式,映射为long或者float | |
3、如果就是字符串,会映射为一个text类型和一个keyword类型 |
日期检测(date_detection)
如果启用了date_detection(默认启用),那么将检查新的字符串字段,看它们的内容是否匹配dynamic_date_formats中指定的任何日期模式。如果找到匹配项,将添加相应格式的一个新日期字段。
参数dynamic_date_formats 默认格式为
[ "strict_date_optional_time","yyyy/MM/dd HH:mm:ss Z||yyyy/MM/dd Z"]
举个例子:
# 创建索引,未指定字段类型
PUT my_index_01/_doc/1
{"create_date":"2015/09/02"}
# 查看索引的映射
GET my_index_01/_mapping
# 返回结果,表示已经动态映射为日期类型
{
"my_index_01" : {
"mappings" : {
"properties" : {
"create_date" : {
"type" : "date",
"format" : "yyyy/MM/dd HH:mm:ss||yyyy/MM/dd||epoch_millis"
}
}
}
}
}
禁用日期检测
如果禁用了日期检测,那么Elasticsearch遇到日期格式的字符串,会动态映射到其他类型(text或keyword),通过设置参数date_detection等于false来禁用动态日期检测。示例如下:
# 禁用date_detection
PUT my_index_01
{"mappings":{"date_detection":false}}
# 创建索引,未指定字段类型
PUT my_index_01/_doc/1
{"create_date":"2015/09/02"}
# 查看索引的映射
GET my_index_01/_mapping
# 返回结果,表示已经动态映射为text类型
{
"my_index_01" : {
"mappings" : {
"date_detection" : false,
"properties" : {
"create_date" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
}
}
自定义检测日期格式
可以自定义动态检测的日期格式。示例如下:
PUT my_index_01
{"mappings":{"dynamic_date_formats":["MM/dd/yyyy"]}}
数字检测(numeric_detection)
虽然JSON支持本地浮点数和整数数据类型,但一些应用程序或语言有时可能将数字呈现为字符串。通常正确的解决方案是显式映射这些字段,但数字检测(默认禁用)可以自动做到这一点,示例如下:
# 开启数字检测
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
{}
# 返回结果,字段 my_float 映射为float类型,字段 my_integer 映射为long类型
{
"my_index_01" : {
"mappings" : {
"numeric_detection" : true,
"properties" : {
"my_float" : {
"type" : "float"
},
"my_integer" : {
"type" : "long"
}
}
}
}
}
动态模板
又称自定义映射,根据匹配条件应用于动态添加的字段
动态模板集是一个object数组,包含至少一个动态模板,结构示例如下:
# 双斜线在执行时需要去掉
PUT my_index_01
{
"mappings": {
"dynamic_templates": [ //1
{
"integers": { // 2
"match_mapping_type": "long", //3
"mapping": { // 4
"type": "integer"
}
}
}
]
}
}
注释1-动态模板集参数名为dynamic_templates,固定的。
注释2-动态模板名称自定义。
注释3-匹配条件,包括match_mapping_type, match, match_pattern, unmatch, path_match, path_unmatch。
注释4-匹配字段使用的类型映射。
动态模板集包含几类重要参数:
(1)match_mapping_type作用于检测数据类型。
(2)match和unmatch或match_pattern作用于字段的名称。
(3)path_match和path_unmatch作用于字段的完整点路径。
可以在动态模板集中的映射使用占位符{name}和{dynamic_type}, {name}表示原始字段名,{dynamic_type}表示检测到的数据类型。
match_mapping_type
match_mapping_type对应的值是JSON解析器检测到的数据类型
**星号可以匹配所有数据类型
案例:将所有证书字段映射为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参数使用模式对字段名进行匹配,而unmatch使用模式来排除通过match匹配的字段。
例如,匹配所有字段名称以long_开头的字符串字段(排除以_text结尾的),并将它们映射为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参数用来调整match参数的行为,可以在字段名上支持完整的Java正则表达式匹配,例如:
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参数的工作方式与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字段)的值复制到顶层的full_name字段,创建新的字段full_name,复制内容到full_name字段中,但是不会影响_source字段内容。