Elasticsearch中的Mapping
1.什么是Mapping?
Mapping用于定义文档的结构以及文档所包含属性(fields)如何被存储和索引。
被ES索引的文档本质就是一些域
或者称为属性
的集合,每一个域
都可以有自己的数据类型。
每一个mapping
都包含了一个文档必要的属性
列表,还可以包含元数据属性(metadata fields)
,例如_source
,它用于自定义如何处理文档的关联元数据。
一句话概括,Mapping用于定义要索引文档的结构及如何被索引。
ES支持两种Mapping的创建方式:
- Dynamic Mapping:动态Mapping
- Explicit Mapping:显式Mapping
2. 动态Mapping
2.1 什么是动态Mapping
ES根据你索引的文档数据,进行自动推算文档属性的数据类型等其他动作,生成对应的Mapping,这就是动态Mapping。Elasticsearch在索引文档自动添加新字段。可以向*映射、内部对象和嵌套字段添加字段。
动态Mapping一般我们只在试验时或者研究数据时才会使用。因为ES自动推算生成的mapping不一定合理。
当索引文档时,如果ES发现文档中有新增加的属性,默认情况下会自动对应增加新属性的mapping
。dynamic
参数控制这个行为。
当启用动态字段映射时,Elasticsearch使用下表中的规则来确定如何映射每个字段的数据类型:
JSON 数据类型 | “dynamic”:“true” | “dynamic”:“runtime” |
---|---|---|
null | 不添加属性mapping | 不添加属性的mapping |
true or false | boolean | boolean |
double | float | double |
integer | long | long |
object | object | No field added |
array | 取决于第一个非null 元素的类型 |
取决于第一个非null 元素的类型 |
日期格式的字符串 | date | date |
数字型的字符串 | float or long | double or long |
非日期或数字格式的字符串 | 带子属性keyword 的text |
keyword |
2.2 实战
下面测试的ES版本为
7.6.2
,不同版本测试结果可能会有差别!
看下面的例子:
我们首先创建一个索引books
:
curl -L -X PUT 'http://192.168.1.102:9200/books' \
-H 'content-type: application/json'
# Output
{
"acknowledged": true,
"shards_acknowledged": true,
"index": "books"
}
查看books
索引定义:
curl -L -X GET 'http://192.168.1.102:9200/books' \
-H 'content-type: application/json'
# Output
{
"books": {
"aliases": {},
"mappings": {},
"settings": {
"index": {
"creation_date": "1629541289738",
"number_of_shards": "1",
"number_of_replicas": "1",
"uuid": "vnI7XlebTraIMhA6CgYBSw",
"version": {
"created": "7060299"
},
"provided_name": "books"
}
}
}
}
可以发现ES帮我们生成的索引定义中,mappings
默认是空的。
添加一条数据到索引books
:
curl -L -X POST 'http://192.168.1.102:9200/books/1' \
-H 'content-type: application/json' \
-d '{
"name":"c++ primer plus第六版",
"version":"6",
"pubilsher":"人民邮电出版社",
"ISBN":"9787115521644",
"publish_time":"2020-07-01"
}'
# Output
{
"_index": "books",
"_type": "1",
"_id": "zOtEaHsBi66Hodhos5sq",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 0,
"_primary_term": 1
}
查看books
索引mapping定义:
curl -L -X GET 'http://192.168.1.102:9200/books/_mappings'
{
"books": {
"mappings": {
"properties": {
"ISBN": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"pubilsher": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"publish_time": {
"type": "date"
},
"version": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
}
}
可以发现,publish_time
被自动映射成了date
数据类型。其他字段被映射成了带子属性keyword
的text
数据类型。
我们再添加一条数据到books
索引,这次我们增加一个属性price
:
curl -L -X POST 'http://192.168.1.102:9200/books/1' \
-H 'content-type: application/json' \
-d '{
"name":"c++ primer plus第六版",
"version":"6",
"pubilsher":"人民邮电出版社",
"ISBN":"9787115521644",
"publish_time":"2020-07-01",
"price": 106.2
}'
再次查看books
索引mapping定义:
curl -L -X GET 'http://192.168.1.102:9200/books/_mappings' \
-H 'content-type: application/json'
{
"books": {
"mappings": {
"properties": {
"ISBN": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"price": {
"type": "float"
},
"pubilsher": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"publish_time": {
"type": "date"
},
"version": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
}
}
ES帮我们自动增加price
的mapping
,并且自动推断为float
数据类型。
这就是dynamic mapping
动态mapping。
3. 显式Mapping
3.1 什么是显示Mapping
显式Mapping允许我们精确地选择如何定义映射,例如:
- 哪些字符串字段应被视为全文字段。
- 字段索引时的分词器
- 字段的数据类型
- 日期的格式
- 控制动态添加字段的映射的自定义规则
- 等等
显示定义Mapping意味着我们对Mapping定义有最大的控制权。
3.2 实战
看下面的例子:
我们首先创建一个索引books
,并显示指定mapping
定义:
curl -L -X PUT 'http://192.168.1.102:9200/books/' \
-H 'content-type: application/json' \
-d '{
"mappings": {
"properties": {
"ISBN": {
"type": "keyword"
},
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"price": {
"type": "float"
},
"pubilsher": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"publish_time": {
"type": "date"
},
"version": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
}'
我们指定了ISBN
的数据类型为keyword
,这意味着我们不需要以此字段做全文检索。
查看books
索引定义:
curl -L -X GET 'http://192.168.1.102:9200/books/'
{
"books": {
"aliases": {},
"mappings": {
"properties": {
"ISBN": {
"type": "keyword"
},
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"price": {
"type": "float"
},
"pubilsher": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"publish_time": {
"type": "date"
},
"version": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
},
"settings": {
"index": {
"creation_date": "1629542862041",
"number_of_shards": "1",
"number_of_replicas": "1",
"uuid": "hLc2e35ZR1OuGxK-B2i1bg",
"version": {
"created": "7060299"
},
"provided_name": "books"
}
}
}
}