Elasticsearch-96-使用动态映射模板定制自己的映射策略

比如说,我们本来没有某个type,或者说没有某个field,但是希望在插入数据的时候,es自动为我们做一个识别,动态映射出这个type的mapping,包括每个field的数据类型,一般用的动态映射就是dynamic mapping

这里有个问题,如果说,我们其实对dynamic mapping有一些独特的需求,比如说,es默认情况下,如果识别到一个数字,比如filed:10,这样的数据,es默认会搞成long类型的,再比如说field:"10"默认就是text类型,还会带一个内置的keyword,我们没法改变

但是我们希望在动态映射的时候,根据我们的需求去映射,而不是按照默认的规则去玩儿

dynamic mapping template

我们可以预先定义一个模板,然后插入数据的时候,相关的field,如果能够根据我们预先定义的规则,匹配某个我们预定义的模板,那么就会根据我们的模板来进行mapping,决定这个field的数据类型

默认的动态映射规则

首先看一下es默认的映射规则是咋样的

1
DELETE my_index

删除之后,直接插入一条数据来看一下

1
2
3
4
5
PUT /my_index/my_type/1
{
"test_string": "hello world",
"test_number": 10
}

查询一下my_index的mapping

1
GET /my_index/_mapping/my_type

返回值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
"my_index": {
"mappings": {
"my_type": {
"properties": {
"test_number": {
"type": "long"
},
"test_string": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
}
}
}

这个就是es默认的动态映射规则.

那我们现在想要的效果是:
test_number这个field,如果是个数字,我们默认就是integer类型的.
test_string这个field,如果是字符串,我们希望默认就是text,内置的field名字叫做raw,而不是keyword,类型还是keyword,保留500个字符

动态映射模板,有两种方式,第一种,是根据新加入的field的默认的数据类型来进行匹配,匹配上某个预定义的模板
第二种是根据新加入的field的名字去匹配预定义的名字或者一个预定义的通配符,然后匹配上某个预定义的模板

根据类型匹配映射模板

删除索引

1
DELETE /my_index

定义模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
PUT /my_index
{
"mappings": {
"my_type": {
"dynamic_templates":[
{
"integers":{ // 模板名称(自定义)
"match_mapping_type":"long", // 匹配的数据类型
"mapping":{
"type":"integer" // 要转换成的数据类型
}
}
},
{
"strings":{
"match_mapping_type":"string",
"mapping":{
"type":"text",
"fields":{
"raw":{ // 内置field的名称
"type":"keyword",
"ignore_above":500
}
}
}
}
}
]
}
}
}

dynamic_templates中加入两个模板,设置好要匹配的数据类型和转换后的数据类型就可以了

添加数据

1
2
3
4
5
PUT /my_index/my_type/1
{
"test_long": 1,
"test_string": "hello world"
}

查询mapping

1
GET /my_index/_mapping/my_type

返回值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
{
"my_index": {
"mappings": {
"my_type": {
"dynamic_templates": [
{
"integers": {
"match_mapping_type": "long",
"mapping": {
"type": "integer"
}
}
},
{
"strings": {
"match_mapping_type": "string",
"mapping": {
"fields": {
"raw": {
"ignore_above": 500,
"type": "keyword"
}
},
"type": "text"
}
}
}
],
"properties": {
"test_long": {
"type": "integer"
},
"test_string": {
"type": "text",
"fields": {
"raw": {
"type": "keyword",
"ignore_above": 500
}
}
}
}
}
}
}
}

上面是我们定义的模板,下面的properties里面就是数据类型等

根据字段名去匹配映射模板

删除索引

1
DELETE /my_index

定义模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
PUT /my_index
{
"mappings": {
"my_type":{
"dynamic_templates":[
{
"string_as_integer":{ // 模板名称
"match_mapping_type":"string", // 匹配的类型
"match":"long_*", // 匹配的名称
"unmatch":"*_text", // 不匹配的名称
"mapping":{
"type":"integer" // 转换后的类型
}
}
}
]
}
}
}

插入数据

1
2
3
4
5
PUT /my_index/my_type/1
{
"long_field": "10",
"long_filed_text": "10"
}

数据中两个数据都是字符串类型,但是long_field是可以匹配到定以好的模板的,所以会转换为integer类型的数据

查询mapping

1
GET /my_index/_mapping/my_type

返回值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
{
"my_index": {
"mappings": {
"my_type": {
"dynamic_templates": [
{
"string_as_integer": {
"match": "long_*",
"unmatch": "*_text",
"match_mapping_type": "string",
"mapping": {
"type": "integer"
}
}
}
],
"properties": {
"long_field": {
"type": "integer"
},
"long_filed_text": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
}
}
}

使用场景

假设一个系统中,每天都会产生一堆数据,这些数据每天的数据都放在一个新的type中,此时就可以预先定义一个模板,搞一个脚本,每天都预先生成一个新的type,里面将你的各个field都匹配到一个你预定义的模板中去,就ok了