【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这水比较深,你把握不住啊!
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

瑟 王

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

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

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

打赏作者

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

抵扣说明:

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

余额充值