上一篇博客【Elasticsearch教程4】Mapping 动态映射讲的动态映射虽然使用简单,但往往不能满足企业的业务场景。比如:
integer就足够了,但是ES会默认成long。.keyword子字段的text类型。动态模板(Dynamic templates)可以满足我们需求,在创建mapping时,先定义好规则,当新字段满足某条规则时,就会按照该规则的预先配置来创建字段。
ES提供了3个角度来定义规则:
| 角度 | 匹配语法 |
|---|---|
| 数据类型 | match_mapping_type |
| 字段名称 | match 和 unmatch |
| 字段全点路径 | path_match 和 path_unmatch |
dynamic_templates是一个数组,可以定义多个规则
{
"mappings": {
"dynamic_templates": [
{
"my_template_name": { #1 自定义动态模板名称
...匹配规则... #2 使用match_mapping_type、match、unmatch等等定义规则
"mapping": { ... } #3 设置符合该规则的mapping配置
}
}
]
}
}
match_mapping_typematch_mapping_type是按照数据类型匹配的,比数据类型是long,而且我们知道该字段的数据范围是不会超过int时,我们可以设置规则匹配为integer。
我们先了解下ES自己根据数据类型创建的字段类型规则:
| JSON数据类型 | ES数据类型 |
|---|---|
| null | 不添加字段 |
| true / false | boolean |
| double | float |
| long | long |
| object | object |
| array | 根据数组中第一个非null值的类型 |
| 通过日期检测的string | date |
| 通过数字检测的string | float 或 long |
| 没有通过上面2个检测的string | 带.keyword子字段的text类型 |
创建如下动态模板:long转integer和stirng转keyword
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_*" | short | short_age |
以int_开头 | "match": "int_*" | integer | integer_people_count |
以long_开头 | "match": "long_*" | long | long_click_count |
以bin_开头 | "match": "bin_*" | binary | bin_head_img |
以ip_开头 | "match": "ip_*" | ip | ip_location |
以text_开头,_ik结尾 | "match": "text_*_ik" | text用ik分词器 | text_name_ik |
以key_开头 | "match": "key_*" | keyword | key_status |
以profit_开头,后面至少跟1位数字,则设为keyword | "match_pattern": "regex","match": "^profit_\d+$" | keyword | prodfit_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_match 和 path_unmatchmatch 和 unmatch 只作用于最后一级的字段名path_match 和 path_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"
}
}
}
}
unmatch 和path_unmatch 不能单独使用match 和 unmatch match_mapping_type的过于简单path_match对用户的设计思想要求比较高,嘎子,path_match这水比较深,你把握不住啊!