Elasticsearch:Dynamic field mapping
2022年4月12日 | by mebius
当 Elasticsearch 在文档中检测到新字段时,默认情况下会动态将该字段添加到类型映射中。 dynamic 参数控制此行为。
你可以通过将 dynamic 参数设置为 true 或 runtime 来明确指示 Elasticsearch 基于传入文档动态创建字段。 启用动态字段映射后,Elasticsearch 使用下表中的规则来确定如何映射每个字段的数据类型。
这篇文章是我之前文章 “Elasticsearch:Dynamic mapping” 的一个补充。
注意:下表中的字段数据类型是 Elasticsearch 动态检测的唯一字段数据类型。 你必须显式映射所有其他数据类型。
JSON data type | “dynamic”: “true” | “dynamic”: “runtime” |
---|---|---|
null | 不添加任何字段 | 不添加任何字段 |
true 或者 false | boolean | boolean |
double | float | double |
long | long | long |
object | object | 不添加任何字段 |
array | 依赖于数组里的第一个非 null 值 | 依赖于数组里的第一个非 null 值 |
通过 date detection 的字符串 | date | date |
通过 numeric detection 的字符串 | float 或者 long | double 或者 long |
不通过 date detection 或者 numberic detection 的字符串 | 含有 .keyword 子字段的 text 类型 | keyword |
你可以在文档和 object 级别禁用动态映射。 将 dynamic 参数设置为 false 会忽略新字段,如果 Elasticsearch 遇到未知字段,把 dynamic 设置为 strict 则会拒绝文档。
提示:使用 update mappingAPI 更新现有字段的 dynamic 设置。
你可以自定义 date detection和 numeric detection 的动态字段映射规则。 要定义可应用于其他动态字段的自定义映射规则,请使用 dynamic_templates。
我们可以使用如下的例子来进行展示:
PUT test_index
{
"mappings": {
"dynamic": "true",
"date_detection": false,
"numeric_detection": false,
"properties": {
"name": {
"properties": {
"firstname": {
"type": "text"
},
"lastname": {
"type": "text"
}
}
}
}
}
}
PUT test_index/_doc/1
{
"null": null,
"bool": true,
"double": 1.0,
"long": 10,
"name": {
"firstname": "xiaoguo",
"lastname": "liu"
},
"subjects": ["Math", "Chinese", "English"],
"date": "2015/09/02",
"numeric": "1.0"
}
GET test_index/_mapping
在上面,我们创建了一个叫做 test_index 的索引。我们把它的 dynamic 属性设置为 true。那么上面最后的一个命令返回的 mapping 值为:
{
"test_index" : {
"mappings" : {
"dynamic" : "true",
"date_detection" : false,
"numeric_detection" : false,
"properties" : {
"bool" : {
"type" : "boolean"
},
"date" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"double" : {
"type" : "float"
},
"long" : {
"type" : "long"
},
"name" : {
"properties" : {
"firstname" : {
"type" : "text"
},
"lastname" : {
"type" : "text"
}
}
},
"numeric" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"subjects" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
}
}
我们可以把 dynamic 设置为 runtime。运行如下的命令:
DELETE test_index
PUT test_index
{
"mappings": {
"dynamic": "runtime",
"date_detection": false,
"numeric_detection": false,
"properties": {
"name": {
"properties": {
"ftgcodeirstname": {
"type": "text"
},
"lastname": {
"type": "text"
}
}
}
}
}
}
PUT test_index/_doc/1
{
"null": null,
"bool": true,
"double": 1.0,
"long": 10,
"name": {
"firstname": "xiaoguo",
"lastname": "liu"
},
"subjects": ["Math", "Chinese", "English"],
"date": "2015/09/02",
"numeric": "1.0"
}
GET test_index/_mapping
那么 test_index 的 mapping 为:
{
"test_index" : {
"mappings" : {
"dynamic" : "runtime",
"date_detection" : false,
"numeric_detection" : false,
"runtime" : {
"bool" : {
"type" : "boolean"
},
"date" : {
"type" : "keyword"
},
"double" : {
"type" : "double"
},
"long" : {
"type" : "long"
},
"numeric" : {
"type" : "keyword"
},
"subjects" : {
"type" : "keyword"
}
},
"properties" : {
"name" : {
"properties" : {
"firstname" : {
"type" : "text"
},
"lastname" : {
"type" : "text"
}
}
}
}
}
}
我们和上面的结果比较一下,还是可以找到它们直接的区别的。
Date detection
如果启用 date_detection(默认),则检查新字符串字段以查看其内容是否与 dynamic_date_formats 中指定的任何日期模式匹配。 如果找到匹配项,则会添加一个具有相应格式的新日期字段。
dynamic_date_formats 的默认值为:
[“strict_date_optional_time”,"yyyy/MM/dd HH:mm:ss Z||yyyy/MM/dd Z"
]
例如:
PUT my-index-000001/_doc/1
{
"create_date": "2015/09/02"
}
上面的命令生成一个叫做my-index-000001 的索引。它的 mapping 是:
GET my-index-000001/_mapping
{
"my-index-000001" : {
"mappings" : {
"properties" : {
"create_date" : {
"type" : "date",
"format" : "yyyy/MM/dd HH:mm:ss||yyyy/MM/dd||epoch_millis"
}
}
}
}
}
在默认的情况下,date detection 是启动的,所以我们可以看到 create_date 被识别为 date 类型的数据。
禁止 date detection
在有些时候,我们可以禁止 date detection,这样摄入的数据可以当做是字符串。可以通过将 date_detection 设置为 false 来禁用动态日期检测:
DELETE my-index-000001
PUT my-index-000001
{
"mappings": {
"date_detection": false
}
}
PUT my-index-000001/_doc/1
{
"create_date": "2015/09/02"
}
GET my-index-000001/_mapping
在上面,我们禁止了 date detection。上面最后一个命令返回的 mapping 值如下:
{
"my-index-000001" : {
"mappings" : {
"date_detection" : false,
"properties" : {
"create_date" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
}
}
显然在这种情况下, create_date 就被当做是一般的 text 来进行处理。
定制 date detection 的日期格式
在上面,我们显示了在默认的情况下日期的检测格式如下:
[“strict_date_optional_time”,"yyyy/MM/dd HH:mm:ss Z||yyyy/MM/dd Z"
]
在实际的很多生产环境中,可能这种格式并不是我们想要的,比如对于中国的许多应用软件,它们的输出格式会和其它地区的格式有所不同。例如:
DELETE my-index-000001
PUT my-index-000001
{
"mappings": {
"dynamic_date_formats": ["yyyy年MM月dd日"]
}
}
PUT my-index-0tgcode00001/_doc/1
{
"create_date": "2022年03月18日"
}
GET my-index-000001/_mapping
在上面,我们重新定义了 date detection 的日期格式,那么上面最好一个命令的返回的值为:
{
"my-index-000001" : {
"mappings" : {
"dynamic_date_formats" : [
"yyyy年MM月dd日"
],
"properties" : {
"create_date" : {
"type" : "date",
"format" : "yyyy年MM月dd日"
}
}
}
}
}
从上面,我们可以看出来 create_date 是一个 date 类型的字段。
Numeric detection
虽然 JSON 支持本机浮点和整数数据类型,但某些应用程序或语言有时可能会将数字呈现为字符串。 通常正确的解决方案是显式映射这些字段,但可以启用 numeric detection(默认情况下禁用)以自动执行此操作:
DELETE my-index-000001
PUT my-index-000001
{
"mappings": {
"numeric_detection": true
}
}
PUT my-tgcodeindex-000001/_doc/1
{
"my_float": "1.0",
"my_integer": "1"
}
GET my-index-000001/_mapping
在上面,我们启动了 number detection,那么最后一个命令返回的结果为:
{
"my-index-000001" : {
"mappings" : {
"numeric_detection" : true,
"properties" : {
"my_float" : {
"type" : "float"
},
"my_integer" : {
"type" : "long"
}
}
}
}
}
更多阅读,请参阅文章 “Elasticsearch:Elasticsearch 中的数据强制匹配”。
文章来源于互联网:Elasticsearch:Dynamic field mapping