一、什么是mapping?
mapping就是映射,可以简单理解为数据类型,只不过是规定了索引中每个字段的数据类型,我们以传统关系型数据库为例,数据库建表的时候,我们DDL依据一般都会指定每个字段的存储类型,例如:varchar、int、datetime等,目的很明确,就是更精确的存储数据,防止数据类型格式混乱,在Elasticsearch中也是这样,创建索引的时候一般也需要指定索引的字段类型,这种方式称为映射(Mapping)
那么指定映射有两种方式,被动创建(也叫动态映射) 和主动创建(也叫显式映射)
1、动态映射
此时字段和映射类型不需要事先定义,只需要存在文档的索引,当向此索引添加数据的时候当遇到不存在的映射字段,ES会根据数据内容自动添加映射字段定义。
相当于对于一个字段,自动的识别并定义其类型
那他自动识别的规则是什么呢?请看下表
左列是给定的数据所属类型,右列识别成对应的ES数据类型
数据类型 | ElasticSearch 数据类型 |
---|---|
null | 不添加任何字段 |
true或者false | boolean类型 |
浮点数据 | float类型 |
integer数据 | long类型 |
object | object类型 |
array | 取决于数组中的第一个非空值的类型。 |
string | 如果此内容通过了日期格式检测,则会被认为是date数据类型 如果此值通过了数值类型检测则被认为是double或者long数据类型 带有关键字子字段会被认为一个text字段 |
但需要注意的是, 一般生产环境下需要禁用动态映射,使用动态映射可能出现以下问题
- 造成集群元数据一直变更,导致不稳定;
- 可能造成数据类型与实际类型不一致;
- 对于一些异常字段或者是扫描类的字段,也会频繁的修改mapping,导致业务不可控。
2、显式映射
这就是我们手动来指定某个字段是什么类型
bash
PUT mapping_demo
{
"settings": {
"analysis": {
"analyzer": {
"ik_smart": {
"type": "ik_smart"
}
}
}
},
"mappings": {
"_doc": {
"properties": {
"name": {
"type": "keyword" // 禁用分词,适用于聚合和排序
},
"city": {
"type": "text",
"analyzer": "ik_smart", // 使用 ik_smart 分析器进行中文分词
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"age": {
"type": "integer" // 指定 age 字段为整数类型
},
"joined": {
"type": "date", // 指定 joined 字段为日期类型
"format": "yyyy-MM-dd||epoch_millis"
}
}
}
}
}
可以看到,我们是在每个字段中,用type来指定对应的映射类型
二、常用映射类型
1、字符串形式的类型
1)text类型
当一个字段是要被全文搜索的,比如Email内容、产品描述,应该使用text类型,text类型会被分词
设置text类型以后,字段内容会被分词,在生成倒排索引以前,字符串会被分析器分成一个一个词项,text类型的字段不用于排序,很少用于聚合
2)keyword类型
keyword类型不会被分词,常用于关键字搜索,比如姓名、email地址、主机名、状态码和标签等
如果字段需要进行过滤(比如查姓名是张三发布的博客)、排序、聚合,keyword类型的字段只能通过精确值搜索到(等值查询),常常被用来过滤、排序和聚合
2、数值形式的类型
数字类型也是我们最常用的类型之一,下面我们看下数字类型的使用
类型 | 取值范围 |
---|---|
long | -263 ~ 263 |
integer | -231 ~ 231 |
short | -215 ~ 215 |
byte | -27 ~ 27 |
double | 64位的双精度 IEEE754 浮点类型 |
float | 32位的双精度 IEEE754 浮点类型 |
half_float | 16位的双精度 IEEE754 浮点类型 |
scaled_float | 缩放类型的浮点类型(理解成保留几位小数) |
- 在满足需求的情况下,优先使用范围小的字段,字段长度越小,索引和搜索的效率越高。
3、日期类型
ES如何处理日期
在ES的内部,时间会被转换为UTC时间(如果声明了时区)并使用从新纪元开始的毫秒数的
长整形数字类型的进行存储,在日期字段上的查询,内部将会转换为使用长整形的毫秒进行范围查询,根据与字段关联的日期格式,聚合和存储字段的结果将转换回字符串
注意点:日期最终都会作为字符串呈现,即使最开始初始化的时候是利用long声明的
日期的格式可以被定制化的,如果没有声明日期的格式,它将会使用默认的格式:
bash
"strict_date_optional_time||epoch_millis"
这意味着它将会接收带时间戳的日期,它将遵守strict_date_optional_time限定的格式(yyyy-MM-dd'T'HH:mm:ss.SSSZ 或者 yyyy-MM-dd)或者毫秒数
举个例子:
bash
PUT mapping_demo/_mapping
{
"properties": {
"datetime": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
}
}
}
# 添加数据
PUT mapping_demo/_doc/2
{
"name":"河北区",
"city":"河北省小区",
"datetime":"2022-02-21 11:35:42"
}
4、布尔类型
boolean类型用于存储文档中的true/false
5、范围类型
顾名思义,范围类型字段中存储的内容就是一段范围,例如年龄30-55岁,日期在2020-12-28到2021-01-01之间等
ES中有6种范围类型
- integer_range
- float_range
- long_range
- double_range
- date_range
- ip_range
bash
PUT mapping_demo/_mapping
{
"properties": {
"age_range": {
"type": "integer_range"
}
}
}
# 指定年龄范围,可以使用 gt、gte、lt、lte。
PUT mapping_demo/_doc/3
{
"name":"张三",
"age_range":{
"gt":20,
"lt":30
}
}