相关阅读:https://www.elastic.co/guide/en/elasticsearch/reference/7.4/dynamic-mapping.html
1. Mapping
Mapping 类似数据库中的 schema 的定义,作用如下:
- 定义索引中的字段的名称
- 定义字段的数据类型,例如字符串、数字、布尔…
- 定义倒排索引相关的配置(采用的 Analyzer、是否被索引)
Mapping 会把 JSON 文档映射成 Lucene 所需要的扁平格式,Mapping 中的字段一旦设定后,禁止直接修改。因为 Lucene 实现的倒排索引生成后不允许直接修改,需要重新建立新的索引,做 Reindex 操作。
2. 字段的数据类型
- 简单类型:
- text / keyword(文本字段中还会额外生成 Keyword 类型的 keyword 字段)
- date
- long
- float
- boolean
- Ipv4 & Ipv6
- 复杂类型-对象和嵌套对象
- 特殊类型
- geo_point & geo_shape / percolator
如下所示示例:
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 47 48
| // 创建索引和文档 PUT mapping_test/_doc/1 { "uid" : "123", "isVip" : false, "isAdmin": "true", "age":19, "heigh":180.65 } // 查询索引 mapping GET mapping_test/_mapping
// 响应及其各字段的 type 值 { "mapping_test" : { "mappings" : { "properties" : { "age" : { "type" : "long" }, "heigh" : { "type" : "float" }, "isAdmin" : { // 不会转为 boolean,因为存入是 text "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } }, "isVip" : { "type" : "boolean" }, "uid" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } } } } } }
|
3. Dynamic Mapping
我们知道在写入文档的时候,如果索引不存在会自动创建索引。由于 Dynamic Mapping 的机制,使得我们无须手动定义 Mappings。ElasticSearch 会自动根据文档信息推算出字段的类型。
但是有时候会推算的不对,例如地理位置信息。当类型设置不对时,会导致一些功能无法正常运行,例如 Range 查询。类型的自动识别规则如下:
JSON 类型 | ElasticSearch 类型 |
---|
字符串 | 1. 匹配日期格式,设置成 date 2. 配置数字设置为 float 或者 long,该选项默认关闭 3. 设置为 text,并且增加 keyword 子字段 |
布尔值 | boolean |
浮点数 | float |
整数 | long |
对象 | object |
数组 | 由第一个非空数值的类型所决定 |
空值 | 忽略 |
这里特别说明下,ElasticSearch 中不提供专门的数组类型,但是任何字段都可以包含多个相同类型的数值。例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| // 此时检索出来的 interests 是 text PUT users/_doc/1 { "name":"onebird", "interests":"reading" }
// 此时检索出来的 interests 是数组 PUT users/_doc/1 { "name":"twobirds", "interests":["reading","music"] }
// mapping 中定义的为 text, 由第一个非空数值的类型所决定 GET users/_mapping
|
4. 控制 Dynamic Mapping
Mapping 可以通过设置 dynamic 的值来控制 Dynamic Mapping 是否可索引等操作,例如下述即是对 mapping_test 修改 dynamic 值为 false:
1 2 3 4
| PUT mapping_test/_mapping { "dynamic": false }
|
dynamic 不同值的规则如下:
- 当 dynamic 设置为 true 时,一旦有新增字段的文档写入,Mapping 也同时被更新
- dynamic 设置为 false 时,Mapping 不会被更新,新增字段的数据无法被索引,但是信息会出现在 _source 中
- dynamic 设置为 strict 时,文档写入失败
当然正如我们开头所说的,对于 mapping 中已有的字段,一旦有数据写入,就不再支持修改字段的类型定义,需要重新建立新的索引,做 Reindex 操作。
下面演示相关示例:
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 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| //新增文档 PUT dynamic_mapping_test/_doc/1 { "newField":"someValue" } // 该字段可以被搜索,数据也在_source中出现 POST dynamic_mapping_test/_search { "query":{ "match":{ "newField":"someValue" } } }
// 修改为dynamic false PUT dynamic_mapping_test/_mapping { "dynamic": false }
// 新增 anotherField PUT dynamic_mapping_test/_doc/10 { "anotherField":"someValue" }
// 该字段不可以被搜索,因为dynamic已经被设置为false POST dynamic_mapping_test/_search { "query":{ "match":{ "anotherField":"someValue" } } }
// 不过anotherField依然存在文档里面 get dynamic_mapping_test/_doc/10
// 查询结果 { "_index" : "dynamic_mapping_test", "_type" : "_doc", "_id" : "10", "_version" : 1, "_seq_no" : 1, "_primary_term" : 1, "found" : true, "_source" : { "anotherField" : "someValue" } }
// 修改为strict PUT dynamic_mapping_test/_mapping { "dynamic": "strict" }
// 写入数据出错,HTTP Code 400 PUT dynamic_mapping_test/_doc/12 { "lastField":"value" }
|