写点什么

如何设计一个高性能 Elasticsearch mapping

  • 2021 年 11 月 11 日
  • 本文字数:2634 字

    阅读完需:约 9 分钟

"name":"lonely wolf",


"age": 18,


"create_date":"2021-05-19 20:45:11",


"update_date":"2021-05-23"


}


插入数据之后,执行 GET index_001 来查询一下索引信息:



可以发现,这时候索引已经被自动创建了,而且 age 字段被 Elasticsearch 定义为 long 类型,update_date 被定义为 data 类型,其他两个字段则被推测为 text 类型。


Elasticsearch 中自动映射类型规则可以通过 dynamic 参数进行配置,dynamic 类型有 4 种:

dynamic=true

默认值。当设置为 true 时,一旦有新字段插入文档,则 mapping 会被同步更新。


我们在上面的文档中再插入一个新文档,新文档新增一个 address 字段:


PUT index_001/_doc/2


{


"name":"lonely wolf2",


"age": 20,


"create_date":"2021-05-23 11:37:11",


"update_date":"2021-05-23",


"address":"广东深圳"


}


然后再查看一下 mapping,可以看到 mapping 已经新增了一个 address 字段,mapping 字段被更新意味着该字段会加入索引:


dynamic=runtime

这个类型和 true 类型非常相似,但是有一个非常大的区别就是,虽然加入新字段也会更新 mapping,但是新加入的字段不会被索引,也就是不会使得索引变大,不过虽然不被索引,但是新加入的字段依然可以被查询,只是查询的代价会更大。所以这种类型一般不建议用在经常查询的条件字段上,而更适合用在一些不确定数据结构的日志类索引中。


修改 dynamic 类型:


PUT index_001/_mapping


{


"dynamic": "runtime"


}


新增一个文档,并加入一个新字段:


PUT index_001/_doc/3


{


"email":"123@qq.com"


}


最后询一下 mapping,可以看到字段属性是 runtime,而且类型是 keyword



下表就是自动创建 mapping 时,Elasticsearch 的映射关系:


| 插入数据类型 | dynamic=true | dynamic=runtime |


| --- | --- | --- |


| null | 不会添加任何字段 | 不会添加任何字段 |


| true 或 false | boolean | boolean |


| double | float | double |


| integer | long | long |


| object | object | object |


| string(通过 date 校验) | date | date |


| string(通过 numreic 校验) | float 或 long | double 或 long |


| string(没有通过 date 或 numreic 校验) | text ,并且同时会创建一个 keyword 子域 | keyword |


| array | 取决于数组中第一个非 null 值 | 取决于数组中第一个非 null 值 |


PS:keyword 表示 不参与分词。

dynamic=false

当设置为 false 时,新加入的字段不会被更新到 mapping,也就是说新字段不会被索引,故以这个字段为条件进行搜索时,无法被搜索到(这一点要注意和 runtime 类型进行区分),不过虽然无法被索引,但是该字段会出现在 _source 中。也就是说该字段不能作为查询条件,但是能被查询出来


接下来我们将 dynamic 修改为 false,并新增一个字段来验证,可以发现新增的字段会出现在 _source 中,但是无法作为条件被查询出来:


dynamic=strict

这种类型最为严格,表示不允许新增一个不在 mapping 中的字段,一旦新增的字段不在 mapping 定义中,则直接报错:


是否可以修改 mapping 中的数据类型

Elasticsearch 中,一旦一个字段被定义在了 mapping 中,是无法被修改的,因为一旦字段被修改了,就会无法被索引(新增字段除外),


【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


所以一般我们需要修改索引的话,都会重建索引,并采用 reindex 操作来迁移数据。

关闭 dynamic mapping

可以通过以下两个配置来关闭 dynamic mapping,以下两个属性默认值均为 true,如果需要关闭,则需要修改为 false


action.auto_create_index: true


index.mapper.dynamic: true


Explicit mapping




Explicit mapping 即:显式映射。也就是说这时候我们需要显示的定义字段类型。


Elasticsearch 中支持的字段类型很多,在这里就举一些比较常用的字段类型:

text 类型

这是最常用的一种类型,存储字符串,用于全文索引。当字段被定义为 text 类型时,默认不能用于聚合,排序等操作:



可以看到,用 text 类型字段排序汇报凑,如果想要允许这些操作,可以通过设置 fielddata=true,如下


PUT my-index-011/_mapping


{


"properties": {


"my_field": {


"type": "text",


"fielddata": true


}


}


}


field 字段存储在堆内存中,因为其涉及到的计算比较消耗性能,所以一般不建议设置 fielddata=true,而是通过建立一个 keyword 子域来实现(默认方式):


PUT index_111


{


"mappings": {


"properties": {


"my_field": {


"type": "text",


"fields": {


"keyword": {


"type": "keyword"


}


}


}


}


}


}


这种定义方式我们可以将一个字段同时作为 textkeyword 类型使用,如果要用于聚合或者排序等操作则可以使用 字段名.keyword 来作为字段名来进行操作:


keyword 类型

这种类型也非常常用,该字段存储的数据表示一个整体,不可被分词,所以一般不会用来定义大本文的全文检索字段,而是用来存储一些结构化的字符串,比如:id,邮箱,标签等。


keyword 类型一般用于聚合,排序等操作。除此之外,该字段还有两种衍生类型:constant_keywordwildcard


  • constant_keyword:一般用于定义常量类型,比如一个索引中某一个字段全部为同一个值,可以定义为这种类型。

  • wildcard:一般用于模糊匹配查询或者正则匹配查询。


如下就是一个模糊匹配查询的示例(可以配合通配符使用,类似于关系型数据库的 like 操作):


GET index_112/_search


{


"query": {


"wildcard": {


"my_wildcard": {


"value": "quitelengthy"


}


}


}


}

date 类型

用于定义日期类型,定义日期类型的同时,可以通过 format 来指定日期的格式:


PUT index_113


{


"mappings": {


"properties": {


"date": {


"type": "date",


"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"


}


}


}


}

numeric 类型

Elasticsearch 中提供了比较多的格式用来表示不同长度的数字类型:


| 数字类型 | 长度 |


| --- | --- |


| long | 64 位有符号整数。范围:-2 的 63 次方到 2 的 63 次方 -1 |


| integer | 32 位有符号整数。范围:-2 的 31 次方到 2 的 31 次方 -1 |


| short | 16 位有符号整数。范围:-32768 到 32767 |


| byte | 8 位有符号整数。范围:-128 到 127 |


| double | 64 位双精度小数 |


| float | 32 位单精度小数 |


| half_float | 16 位单精度小数 |


| scaled_float | 带有缩放因子的浮点数,一般适用于存放金额之类的数据。比如 18.88 元,缩放因子是 100,那么在索引时会被索引为 1888(即:原值 * 缩放因子) |


| unsigned_long | 64 位无符号整数。范围:0 到 2 的 64 次方减 1 |


定义方式如下所示:

评论

发布
暂无评论
如何设计一个高性能Elasticsearch mapping