述
比如说,我们本来没有某个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
5PUT /my_index/my_type/1
{
"test_string": "hello world",
"test_number": 10
}
查询一下my_index的mapping1
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
31PUT /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
5PUT /my_index/my_type/1
{
"test_long": 1,
"test_string": "hello world"
}
查询mapping1
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
19PUT /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
5PUT /my_index/my_type/1
{
"long_field": "10",
"long_filed_text": "10"
}
数据中两个数据都是字符串类型,但是long_field是可以匹配到定以好的模板的,所以会转换为integer类型的数据
查询mapping1
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了