映射配置
在创建索引时,可以预先定义字段的类型(映射类型)及相关属性。
数据库建表的时候,我们DDL依据一般都会指定每个字段的存储类型,例如:varchar、int、datetime等,目的很明确,就是更精确的存储数据,防止数据类型格式混乱,在Elasticsearch中也是这样,创建索引的时候一般也需要指定索引的字段类型,这种方式称为映射(Mapping)。
被动创建(动态映射)
此时字段和映射类型不需要事先定义,只需要存在文档的索引,当向此索引添加数据的时候当遇到不存在的映射字段,ES会根据数据内容自动添加映射字段定义。使用动态映射的时候,根据传递请求数据的不同会创建对应的数据类型。
禁止动态映射
一般生产环境下需要禁用动态映射,使用动态映射可能出现以下问题
- 造成集群元数据一直变更,导致不稳定;
- 可能造成数据类型与实际类型不一致;
禁用动态映射,动态mapping
的dynamic
字段进行配置,可选值及含义如下
- true:支持动态扩展,新增数据有新的字段属性时,自动添加对于的mapping,数据写入成功
- false:不支持动态扩展,新增数据有新的字段属性时,直接忽略,数据写入成功
- strict:不支持动态扩展,新增数据有新的字段时,报错,数据写入失败
主动创建(显示映射)
我们需要对字段除了数据结构定义更多的限制的时候,动态映射创建的内容很可能不符合我们的需求,所以可以使用PUT {index}/mapping
来更新指定索引的映射内容。
映射类型
我们要创建映射必须还要知道映射类型,否则就会走默认的映射类型,下面我们看看常用的映射类型。
准备工作
bash
# 创建一个索引
PUT mapping_demo
字符串类型
符串类型可以被设置为以下几种类型
text
当一个字段是要被全文搜索的,比如Email内容、产品描述,应该使用text类型,text类型会被分词。设置text类型以后,字段内容会被分词,在生成倒排索引以前,字符串会被分析器分成一个一个词项,text类型的字段不用于排序,很少用于聚合 。
keyword
keyword类型不会被分词,常用于关键字搜索,比如姓名、email地址、主机名、状态码和标签等。如果字段需要进行过滤(比如查姓名是张三发布的博客)、排序、聚合,keyword类型的字段只能通过精确值搜索到,常常被用来过滤、排序和聚合。
两者区别
它们的区别在于text
会对字段进行分词处理而keyword
则不会进行分词。如果字段是text
类型,存入的数据会先进行分词,然后将分完词的词组存入索引,而keyword
则不会进行分词,直接存储,这样划分数据更加节省内存。
使用案例
先创建一个映射,name是keyword类型,描述是text类型的
bash
PUT mapping_demo/_mapping
{
"properties": {
"name": {
"type": "keyword"
},
"city": {
"type": "text",
"analyzer": "ik_smart"
}
}
}
# 插入数据
PUT mapping_demo/_doc/1
{
"name":"北京小区",
"city":"北京市昌平区回龙观街道"
}
# 对于keyword的name字段进行精确查询
GET mapping_demo/_search
{
"query": {
"term": {
"name": "北京小区"
}
}
}
# 对于text的city进行模糊查询
GET mapping_demo/_search
{
"query": {
"term": {
"city": "北京市"
}
}
}
数字类型
数字类型也是我们最常用的类型之一,下面我们看下数字类型的使用。
- 在满足需求的情况下,优先使用范围小的字段,字段长度越小,索引和搜索的效率越高。
日期类型
JSON表示日期
JSON没有表达日期的数据类型,所以在ES里面日期只能是下面其中之一。
- 格式化的日期字符串,比如:
"2015-01-01"
or"2015/01/01 12:10:30"
- 用数字表示的从新纪元开始的毫秒数
- 用数字表示的从新纪元开始的秒数(epoch_second)
ES如何处理日期
在ES的内部,时间会被转换为UTC时间(如果声明了时区)并使用从新纪元开始的毫秒数的
长整形数字类型的进行存储,在日期字段上的查询,内部将会转换为使用长整形的毫秒进行范围查询,根据与字段关联的日期格式,聚合和存储字段的结果将转换回字符串。
默认日期格式
日期的格式可以被定制化的,如果没有声明日期的格式,它将会使用默认的格式。
"strict_date_optional_time||epoch_millis"
意味着它将会接收带时间戳的日期,它将遵守strict_date_optional_time限定的格式(yyyy-MM-dd'T'HH:mm:ss.SSSZ
或者 yyyy-MM-dd
)或者毫秒数。
日期格式示例
javascript
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"
}
日期类型参数
布尔类型
boolean类型用于存储文档中的true/false
范围类型
范围类型字段中存储的内容就是一段范围,例如年龄30-55岁,日期在2020-12-28到2021-01-01之间等。
es中有六种范围类型:
- integer_range
- float_range
- long_range
- double_range
- date_range
- ip_range
使用实例
javascript
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
}
}