1. 简述

ES支持动态映射。即往ES中存储文档之前,可以不用预先定义索引、映射类型、字段等结构,ES内部会完成动态映射。

  1. PUT data/_doc/1
  2. { "count": 5 }

上述例子:动态映射建立索引data、文档映射类型_doc和名称为count且数据类型为long的字段。

自动检测和添加新字段称为动态映射。可以自定义动态映射规则。

2. 动态字段映射

2.1 概念说明

默认情况下,往文档中插入以前没有的字段(新字段)时,Elasticsearch会将新字段添加到类型映射中(动态映射)。
可以在文档(document)和对象(Object)级别禁用此行为(是否可以插入新字段),方法是将dynamic参数设置为false(忽略新字段)或strict(遇到未知字段时抛出异常)
如果开启了动态字段映射开关,ES将根据如下对应关系决定它的数据类型:

输入的json字段类型 ES动态映射为的数据类型
null 没有字段被添加(被忽略,相当于无效输入)
true 或者 false boolean类型
浮点数(floating point number) float类型
integer long类型
对象(Object) object类型
数组(array) Array类型,元素类型取决于数组中的第一个null值。
字符串(string)
- 如果值通过日期检测,则为date类型
- 如果值通过数字检测,则为float类型或long类型
- 否则,则为Text类型

默认日期字符串格式为:yyyy/MM/dd HH:mm:ss||yyyy/MM/dd||epoch_millis
提示:表格中的字段类型支持动态字段映射,除此之外,其他数据类型必须通过显式映射(手动定义字段映射)

2.2 验证实例

2.2.1 新增文档

  1. PUT dynamic_index/doc/1
  2. {
  3. "name": "八宝粥",
  4. "desc": null,
  5. "price": 5.8,
  6. "month": 18,
  7. "info":{
  8. "place":"广东揭阳",
  9. "category":"food"
  10. },
  11. "date":"2019/12/29 18:00:02",
  12. "flavour":["sour","sweet","bitter","hot"],
  13. "model":["125.26","120","450ml"]
  14. }

2.2.1 查询字段定义

  1. GET dynamic_index/_mapping

2.2.1 查询映射结果

从返回结果可以得出:

输入 映射
“name”: “八宝粥”,


“name” : {
“type” : “text”,
“fields” : {
“keyword” : {
“type” : “keyword”,
“ignore_above” : 256
}
}
}
“desc”: null, 没有被动态映射并添加到索引中(相当于无效输入)
“price”: 5.8, “price” : {
“type” : “float”
}
“month”: 18, “month” : {
“type” : “long”
},
“date”:”2019/12/29 18:00:02”, “date” : {
“type” : “date”,
“format” : “yyyy/MM/dd HH:mm:ss||yyyy/MM/dd||epoch_millis”
},

输入”desc”: null
“price”: 5.8,
“month”: 18,

  1. {
  2. "dynamic_index" : {
  3. "mappings" : {
  4. "doc" : {
  5. "properties" : {
  6. "date" : {
  7. "type" : "date",
  8. "format" : "yyyy/MM/dd HH:mm:ss||yyyy/MM/dd||epoch_millis"
  9. },
  10. "flavour" : {
  11. "type" : "text",
  12. "fields" : {
  13. "keyword" : {
  14. "type" : "keyword",
  15. "ignore_above" : 256
  16. }
  17. }
  18. },
  19. "info" : {
  20. "properties" : {
  21. "category" : {
  22. "type" : "text",
  23. "fields" : {
  24. "keyword" : {
  25. "type" : "keyword",
  26. "ignore_above" : 256
  27. }
  28. }
  29. },
  30. "place" : {
  31. "type" : "text",
  32. "fields" : {
  33. "keyword" : {
  34. "type" : "keyword",
  35. "ignore_above" : 256
  36. }
  37. }
  38. }
  39. }
  40. },
  41. "model" : {
  42. "type" : "text",
  43. "fields" : {
  44. "keyword" : {
  45. "type" : "keyword",
  46. "ignore_above" : 256
  47. }
  48. }
  49. },
  50. "month" : {
  51. "type" : "long"
  52. },
  53. "name" : {
  54. "type" : "text",
  55. "fields" : {
  56. "keyword" : {
  57. "type" : "keyword",
  58. "ignore_above" : 256
  59. }
  60. }
  61. },
  62. "price" : {
  63. "type" : "float"
  64. }
  65. }
  66. }
  67. }
  68. }
  69. }

3. 日期检测

如果启用了date_detection(默认启用),则会检查新插入的字符串字段,看内容是否与在dynamic_date_formats指定的日期格式匹配,如果匹配,则字段映射为date类型,否则,映射为Text类型。

dynamic_date_formats的默认值(格式)为:
[ "strict_date_optional_time","yyyy/MM/dd HH:mm:ss Z||yyyy/MM/dd Z"]

3.1 验证实例1(映射为date类型)

3.1.1 新增文档

新增文档,日期字符串内容与默认日期格式一致

  1. PUT date_detection_ok_index/_doc/1
  2. {
  3. "create_date": "2019/09/02 20:12:35"
  4. }

3.1.2 查询映射定义

  1. GET date_detection_ok_index/_mapping

3.1.3 映射结果

  1. {
  2. "date_detection_ok_index" : {
  3. "mappings" : {
  4. "_doc" : {
  5. "properties" : {
  6. "create_date" : {
  7. "type" : "date",
  8. "format" : "yyyy/MM/dd HH:mm:ss||yyyy/MM/dd||epoch_millis"
  9. }
  10. }
  11. }
  12. }
  13. }
  14. }

3.2 验证实例2(映射为text类型)

3.2.1 新增文档

  1. PUT date_detection_no_index/_doc/1
  2. {
  3. "create_date": "2019-09-02 20:12:35"
  4. }

3.2.1 查询映射定义

  1. GET date_detection_no_index/_mapping

3.2.1 映射结果

  1. {
  2. "date_detection_no_index" : {
  3. "mappings" : {
  4. "_doc" : {
  5. "properties" : {
  6. "create_date" : {
  7. "type" : "text",
  8. "fields" : {
  9. "keyword" : {
  10. "type" : "keyword",
  11. "ignore_above" : 256
  12. }
  13. }
  14. }
  15. }
  16. }
  17. }
  18. }
  19. }

4. 禁用日期检测

在定义映射的时候,可以通过将date_detection设置为false,达到禁用动态日期检测,如下:

4.1 验证实例

4.1.1 新增定义

将该索引的映射中的date_detection属性设置为false。后续插入内容无论是何种日期格式,都将不会被检测并转换为date类型。

  1. PUT disable_date_detection_index
  2. {
  3. "mappings": {
  4. "_doc": {
  5. "date_detection": false
  6. }
  7. }
  8. }

4.1.2 插入文档

  1. PUT disable_date_detection_index/_doc/1
  2. {
  3. "create_date": "2019-09-02 20:12:35"
  4. }

4.1.3 查询映射定义

  1. GET disable_date_detection_index/_mapping

4.1.4 映射结果

  1. {
  2. "disable_date_detection_index" : {
  3. "mappings" : {
  4. "_doc" : {
  5. "date_detection" : false,
  6. "properties" : {
  7. "create_date" : {
  8. "type" : "text",
  9. "fields" : {
  10. "keyword" : {
  11. "type" : "keyword",
  12. "ignore_above" : 256
  13. }
  14. }
  15. }
  16. }
  17. }
  18. }
  19. }
  20. }

5. 自定义检测日期格式

可以自定义 dynamic_date_formats 格式以支持自定义的日期格式:

5.1 新增定义(自定义日期格式)

  1. PUT custom_date_format_index
  2. {
  3. "mappings": {
  4. "_doc": {
  5. "dynamic_date_formats": ["MM/dd/yyyy"]
  6. }
  7. }
  8. }

5.2 插入数据

示例1:插入日期字符串“13/31/2020”(日期不符合实际)

  1. PUT /custom_date_format_index/_doc/1
  2. {
  3. "create_date":"13/31/2020"
  4. }

转换结果:不符合实际情况(13月)的日期字符串,尽管与自定义的日期检测格式形似,但是转换后的字段数据类型为TEXT

  1. {
  2. "custom_date_format_index" : {
  3. "mappings" : {
  4. "_doc" : {
  5. "dynamic_date_formats" : [
  6. "MM/dd/yyyy"
  7. ],
  8. "properties" : {
  9. "create_date" : {
  10. "type" : "text",
  11. "fields" : {
  12. "keyword" : {
  13. "type" : "keyword",
  14. "ignore_above" : 256
  15. }
  16. }
  17. }
  18. }
  19. }
  20. }
  21. }
  22. }

示例2:
插入日期字符串“05/31/2020”(日期符合实际)

  1. PUT /custom_date_format_index/_doc/1
  2. {
  3. "birth_date":"05/31/2020"
  4. }

转换结果:日期格式字符串添加到es索引时,自动映射的字段类型为date类型,自定义日期检测生效

  1. {
  2. "custom_date_format_index" : {
  3. "mappings" : {
  4. "_doc" : {
  5. "dynamic_date_formats" : [
  6. "MM/dd/yyyy"
  7. ],
  8. "properties" : {
  9. "birth_date" : {
  10. "type" : "date",
  11. "format" : "MM/dd/yyyy"
  12. }
  13. }
  14. }
  15. }
  16. }
  17. }

6.数字检测

ES 默认是禁用数字检测属性。我们可以在映射定义的时候,显式启用数字检测,例如:

6.1 新增定义

  1. PUT numeric_detection_index
  2. {
  3. "mappings": {
  4. "_doc": {
  5. "numeric_detection": true
  6. }
  7. }
  8. }

6.2 插入文档

  1. PUT numeric_detection_index/_doc/1
  2. {
  3. "my_float": "1.0",
  4. "my_integer": "1"
  5. }

6.3 查询转换结果

查询

  1. GET numeric_detection_index/_mapping

结果:

  1. {
  2. "numeric_detection_index" : {
  3. "mappings" : {
  4. "_doc" : {
  5. "numeric_detection" : true,
  6. "properties" : {
  7. "my_float" : {
  8. "type" : "float"
  9. },
  10. "my_integer" : {
  11. "type" : "long"
  12. }
  13. }
  14. }
  15. }
  16. }
  17. }