【Elasticsearch教程5】Mapping 动态模板 Dynamic templates

一、前言

上一篇博客【Elasticsearch教程4】Mapping 动态映射讲的动态映射虽然使用简单,但往往不能满足企业的业务场景。比如:

  • 对于整数,一般用integer就足够了,但是ES会默认成long
  • 对于字符串(邮箱,住址),一般我们不用分词,但是ES总会设成带.keyword子字段的text类型。

动态模板(Dynamic templates)可以满足我们需求,在创建mapping时,先定义好规则,当新字段满足某条规则时,就会按照该规则的预先配置来创建字段。

二、动态模板的类型

ES提供了3个角度来定义规则:

  1. 数据类型(data type)
  2. 字段名称(field name)
  3. 字段全点路径(full dotted path to the field)
角度匹配语法
数据类型match_mapping_type
字段名称match unmatch
字段全点路径path_matchpath_unmatch

三、动态模板的语法

dynamic_templates是一个数组,可以定义多个规则

{
	"mappings": {
		"dynamic_templates": [
    		{
      			"my_template_name": {  	#1 自定义动态模板名称
        		...匹配规则...        	#2 使用match_mapping_type、match、unmatch等等定义规则 
       		 	"mapping": { ... } 		#3 设置符合该规则的mapping配置
        		}
    		}
  		]
	}
}

四、match_mapping_type

match_mapping_type是按照数据类型匹配的,比数据类型是long,而且我们知道该字段的数据范围是不会超过int时,我们可以设置规则匹配为integer

4.1 ES动态字段映射

我们先了解下ES自己根据数据类型创建的字段类型规则:

JSON数据类型ES数据类型
null不添加字段
true / falseboolean
doublefloat
longlong
objectobject
array根据数组中第一个非null值的类型
通过日期检测的stringdate
通过数字检测的stringfloat 或 long
没有通过上面2个检测的string.keyword子字段的text类型

4.2 自定义数据类型规则

创建如下动态模板:longintegerstirngkeyword

PUT pigg_test
{
  "mappings": {
    "dynamic_templates": [
      {
        "my_template_long": {
          "match_mapping_type": "long",
          "mapping": {
            "type": "integer"
          }
        }
      },
      {
        "my_template_string": {
          "match_mapping_type": "string",
          "mapping": {
            "type": "keyword"
          }
        }
      }
    ]
  }
}

插入一笔测试数据

PUT pigg_test/_doc/1
{
  "name": "亚瑟王",
  "age": 33
}

通过GET pigg_test/_mapping查询发现ES创建的字段类型确实符合上面定义的模板

      "properties" : {
        "age" : {
          "type" : "integer"
        },
        "name" : {
          "type" : "keyword"
        }
      }

五、match unmatch

在企业开发中用的最多的其实还是这个字段名称匹配。

  • match:字段名称匹配某规则
  • unmatch :字段名称不匹配某规则
  • match_pattern:设置为regex,配合match unmatch 使用正则表达式
  • 注意:对于嵌套对象,match unmatch 只作用于最后一级字段名

比如企业常用动态表单场景,我们不知道一个表有多少字段,也不知道字段的类型,也不知道某字段是否要分词。我们可以做如下约定:

规则表达式ES类型字段名称案例
short_开头"match": "short_*"shortshort_age
int_开头"match": "int_*"integerinteger_people_count
long_开头"match": "long_*"longlong_click_count
bin_开头"match": "bin_*"binarybin_head_img
ip_开头"match": "ip_*"ipip_location
text_开头,_ik结尾"match": "text_*_ik"textik分词器text_name_ik
key_开头"match": "key_*"keywordkey_status
profit_开头,后面至少跟1位数字,则设为keyword"match_pattern": "regex","match": "^profit_\d+$"keywordprodfit_1

我们先选择其中3个作为测试例子:

PUT pigg_test
{   
  "mappings": {
    "dynamic_templates": [
      {
        "string_to_integer": {
          "match_mapping_type": "string",
          "match":   "int_*",
          "mapping": {
            "type": "integer"
          }
        }
      },
      {
        "string_to_long": {
          "match_mapping_type": "string",
          "match":   "long_*",
          "mapping": {
            "type": "long"
          }
        }
      },
      {
        "string_to_text_ik": {
          "match_mapping_type": "string",
          "match":   "text_*_ik*",
          "mapping": {
            "type": "text",
            "analyzer": "ik_max_word"
          }
        }
      }
    ]
  }
}

插入测试数据:

PUT pigg_test/_doc/1
{
  "int_age": "18",
  "long_click_count": "100000",
  "text_name_ik": "亚瑟王"
}

通过GET pigg_test/_mapping查询发现ES创建的字段类型确实符合上面定义的模板

"properties" : {
        "int_age" : {
          "type" : "integer"
        },
        "long_click_count" : {
          "type" : "long"
        },
        "text_name_ik" : {
          "type" : "text",
          "analyzer" : "ik_max_word"
        }
}

六、path_matchpath_unmatch

  • 上面一级说了match unmatch 只作用于最后一级的字段名
  • 对于一个有多层的内嵌对象,可以用path_matchpath_unmatch

下面设置person.*下除了age都是text类型

PUT pigg_test
{
    "mappings":{
        "dynamic_templates":[
            {
                "test_float":{
                    "path_match":"person.*",
                    "path_unmatch":"*.age",
                    "mapping":{
                        "type":"text"
                    }
                }
            },
            {
                "test_float":{
                    "path_match":"*.age",
                    "mapping":{
                        "type":"integer"
                    }
                }
            }
        ]
    }
}

插入测试数据:

PUT pigg_test/_doc/1
{
  "person": {
    "count": "100",
    "age": "100"
  }
}

通过GET pigg_test/_mapping查询发现ES创建的字段类型确实符合上面定义的模板

"properties" : {
     "person" : {
          "properties" : {
            "age" : {
              "type" : "integer"
            },
            "count" : {
              "type" : "text"
            }
         }
     }
}

七、注意事项

  • 所有null和空数组[]都属于无效的值,不会匹配任务动态模板的规则
  • 匹配规则时,是按照模板的配置顺序依次进行对比的,使用最先匹配到的那个模板
  • unmatch path_unmatch 不能单独使用
  • 动态模板的3中方式中推荐match unmatch
  • 因为 match_mapping_type的过于简单
  • path_match对用户的设计思想要求比较高,嘎子,path_match这水比较深,你把握不住啊!
### 修改Elasticsearch 1.5.2版本中的映射配置 在Elasticsearch 1.5.2中,更新或更改索引映射设置是一个重要操作。需要注意的是,在创建索引之后,默认情况下不允许直接修改已存在的字段映射。然而,有几种方法可以在一定条件下实现这一目标。 #### 动态模板 (Dynamic Templates) 如果希望某些类型的字段自动应用特定的映射规则而不必手动指定每一个新字段,则可以利用动态模板功能来预先定义这些规则[^1]。 ```json PUT /my_index/_mapping { "dynamic_templates": [ { "strings_as_keywords": { "match_mapping_type": "string", "mapping": { "type": "multi_field", "fields": { "raw": {"type": "string", "index": "not_analyzed"} } } } } ] } ``` 此代码片段展示了如何为字符串类型的数据添加未分析(`not_analyzed`)子字段作为关键词处理方式的例子。 #### 添加新的字段到现有映射 对于新增加的文档属性,可以直接通过插入含有该属性的新文档让Elasticsearch自动生成相应的映射;也可以显式地向已有索引添加单个字段而无需重建整个索引结构: ```json POST /existing_index/doc/ { "newField": "value" } ``` 或者更正式的方式是发送请求给`_mapping/type`端点以声明具体的变化: ```json PUT /existing_index/_mapping/doc { "properties": { "newField": { "type": "date", "format": "yyyy-MM-dd HH:mm:ss||epoch_millis" } } } ``` 这里指定了一个新的日期型字段及其格式化模式[^2]。 #### 使用别名(Aliases)与重新索引(Reindexing) 当确实需要改变已经存在且被使用的字段映射时——比如从文本变为数值或其他不可兼容变更的情况下,通常推荐的做法是建立一个具有所需映射的新索引,并将旧数据迁移过来。这期间可借助于别名机制保持服务连续性[^3]: 1. 创建带有期望映射的新索引; 2. 将原索引里的全部记录复制至新位置; 3. 更新应用程序指向新的索引路径; 4. 删除不再需要的老版资源。 这种方法虽然较为复杂但也最为安全可靠,能有效防止因直接改动引起的各种潜在风险。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

瑟王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值