目录
Disabling date detection (禁用日期检测)
Customizing detected date formats (自定义检测到的日期格式)
Elasticsearch最重要的功能之一就是它会尽量避开我们的视线,让我们尽快开始探索我们的数据。要为文档编制索引,不必首先创建索引、定义映射类型和定义字段 — 我们只需为文档编制索引,索引、类型和字段将自动显示:
PUT data/_doc/1
{ "count": 5 }
创建data索引、_doc映射类型和名为count且数据类型为long的字段。
自动检测和添加新字段称为动态映射。动态映射规则可以通过以下方式进行自定义以满足我们的目的:
Dynamic field mappings
管理动态字段发现的规则。
当Elasticsearch在文档中检测到一个新字段时,它会在默认情况下动态地将该字段添加到类型映射中。动态参数控制此行为。
通过将动态参数设置为true或runtime,可以显式指示Elasticsearch基于传入文档动态创建字段。启用动态字段映射后,Elasticsearch使用下表中的规则来确定如何映射每个字段的数据类型。
下表中的字段数据类型是Elasticsearch动态检测的唯一字段数据类型。必须显式映射所有其他数据类型
JSON data type |
|
|
| No field added | No field added |
|
|
|
|
|
|
|
|
|
|
|
|
| Depends on the first non- | Depends on the first non- |
|
|
|
|
|
|
|
|
|
object始终映射为properties部分的一部分,即使动态参数设置为runtime。
我们可以在document和object级别禁用动态映射。将动态参数设置为false将忽略新字段,如果Elasticsearch遇到未知字段,strict将拒绝文档。
使用更新映射API更新现有字段的动态设置。
可以自定义用于日期检测和数字检测的动态字段映射规则。要定义可应用于其他动态字段的自定义映射规则,请使用动态模板(dynamic templates)。
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"
}
GET my-index-000001/_mapping
create_date字段被做为date类型字段增加,格式为:"yyyy/MM/dd HH:mm:ss Z||yyyy/MM/dd Z"
.
Disabling date detection (禁用日期检测)
通过将date_detection设置为false,可以禁用动态日期检测:
PUT my-index-000001
{
"mappings": {
"date_detection": false
}
}
PUT my-index-000001/_doc/1
{
"create": "2015/09/02"
}
这个create 字段会被做为text类型字段增加。
Customizing detected date formats (自定义检测到的日期格式)
或者,dynamic_date_formats可以被定制,以支持我们自己的日期格式:
PUT my-index-111
{
"mappings": {
"dynamic_date_formats": ["MM/dd/yyyy"]
}
}
PUT my-index-111/_doc/1
{
"create_date": "09/25/2015"
}
Numeric detection (数字检测)
虽然JSON支持本机浮点和整数数据类型,但某些应用程序或语言有时可能会将数字呈现为字符串。通常正确的解决方案是显式映射这些字段,但是可以启用数字检测(默认情况下禁用)来自动执行此操作:
PUT my-index-000001
{
"mappings": {
"numeric_detection": true
}
}
PUT my-index-000001/_doc/1
{
"my_float": "1.0",
"my_integer": "1"
}
my_float字段 作为float类型增加。
my_integer字段作为long类型增加。
Dynamic templates
为动态添加的字段配置映射的自定义规则。
索引模板允许我们为新索引配置默认映射、设置和别名,无论是自动创建的还是显式创建的。
动态模板允许我们更好地控制Elasticsearch如何映射数据,而不是默认的动态字段映射规则。通过将动态参数设置为true或runtime,可以启用动态映射。然后,可以使用动态模板定义自定义映射,这些映射可以基于匹配条件应用于动态添加的字段:
- match_mapping_type 对Elasticsearch检测到的数据类型进行操作。
- match and unmatch 在字段名上使用模式进行匹配。
-
path_match and path_unmatch 在字段的完整虚线路径上操作。
-
如果动态模板没有定义匹配类型、匹配或路径匹配,则它不会匹配任何字段。我们仍然可以在批量请求的动态模板部分按名称引用模板。
使用映射规范中的{name}和{dynamic_type}模板变量作为占位符。
动态模板指定为命名对象的数组:
"dynamic_templates": [
{
"my_template_name": { (1)
... match conditions ... (2)
"mapping": { ... } (3)
}
},
...
]
1、模板名称可以是任何字符串值。
2、匹配条件可以包括:匹配映射类型(match_mapping_type)、匹配(match)、匹配模式(match_pattern)、不匹配(unmatch)、路径匹配(path_match)、路径不匹配(path_unmatch)。
3、匹配字段应使用的映射。
验证动态模板
如果提供的映射包含无效的映射片段,则返回验证错误。在索引时应用动态模板时,以及在大多数情况下更新动态模板时,会发生验证。在某些情况下,提供无效的映射片段可能会导致动态模板的更新或验证失败:
- 如果未指定匹配的映射类型,但模板对至少一个预定义的映射类型有效,则认为映射段有效。但是,如果与模板匹配的字段被索引为不同类型,则在索引时会返回验证错误。例如,将动态模板配置为不匹配映射类型(no
match_mapping_type
)被视为有效的字符串类型,但如果将与动态模板匹配的字段索引为long,则会在索引时返回验证错误。建议将match_mapping_type配置为预期的JSON类型,或在映射片段中配置所需的类型。 - 如果在映射片段中使用了{name}占位符,则更新动态模板时将跳过验证。这是因为当时字段名未知。相反,在索引时应用模板时会进行验证。
模板按顺序处理 — 第一个匹配的模板获胜。通过更新映射API放置新的动态模板时,将覆盖所有现有模板。这允许动态模板在最初添加后重新排序或删除。
在动态模板映射运行时字段
如果希望Elasticsearch将特定类型的新字段动态映射为运行时字段,请在索引映射中设置“dynamic”:“runtime”。这些字段没有索引,在查询时从_source加载。
或者,可以使用默认的动态映射规则,然后创建动态模板,将特定字段映射为运行时字段。在索引映射中设置“dynamic”:“true”,然后创建一个动态模板,将某个类型的新字段映射为运行时字段。
假设我们有数据,其中每个字段都以ip_开头。基于动态映射规则,Elasticsearch将任何通过数字检测的字符串映射为float或long。但是,可以创建一个动态模板,将新字符串映射为ip类型的运行时字段。
下面的请求定义了一个名为strings_as_ip的动态模板。当Elasticsearch检测到与ip*模式匹配的新字符串字段时,它会将这些字段映射为ip类型的运行时字段。因为ip字段不是动态映射的,所以可以将此模板与“dynamic”:“true”或“dynamic”:“runtime”一起使用。
PUT my-index-000001/
{
"mappings": {
"dynamic_templates": [
{
"strings_as_ip": {
"match_mapping_type": "string",
"match": "ip*",
"runtime": {
"type": "ip"
}
}
}
]
}
}
match_mapping_type:
匹配映射类型(match_mapping_type)是JSON解析器检测到的数据类型。因为JSON不区分long和整数,也不区分double和float,所以它总是选择更广泛的数据类型,比如long代表整数,double代表浮点数。
Elasticsearch自动检测以下数据类型:
JSON data type |
|
|
| No field added | No field added |
|
|
|
|
|
|
|
|
|
|
|
|
| Depends on the first non- | Depends on the first non- |
|
|
|
|
|
|
|
|
|
objects 始终映射为属性部分的一部分,即使动态参数设置为运行时也是如此。
使用通配符(*)匹配所有数据类型。
例如,如果要将所有整型字段映射为整数而不是长型,将所有字符串字段映射为文本和关键字,则可以使用以下模板:
PUT my-index-000001
{
"mappings": {
"dynamic_templates": [
{
"integers": {
"match_mapping_type": "long",
"mapping": {
"type": "integer"
}
}
},
{
"strings": {
"match_mapping_type": "string",
"mapping": {
"type": "text",
"fields": {
"raw": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
]
}
}
PUT my-index-000001/_doc/1
{
"my_integer": 5, (1)
"my_string": "Some string" (2)
}
1、my_integer 字段被映射为 integer类型。
2、my_string 字段被映射为text,带有一个 keyword multi field。
match and unmatch:
match参数使用模式匹配字段名,而unmatch使用模式排除匹配的字段。
match_pattern参数调整match参数的行为,以支持在字段名上匹配完整的Java正则表达式,而不是简单的通配符。例如:
"match_pattern": "regex",
"match": "^profit_\d+$"
以下示例匹配名称以long_开头的所有字符串字段(以_text结尾的字段除外),并将其映射为long字段:
PUT my-index-000001
{
"mappings": {
"dynamic_templates": [
{
"longs_as_strings": {
"match_mapping_type": "string",
"match": "long_*",
"unmatch": "*_text",
"mapping": {
"type": "long"
}
}
}
]
}
}
PUT my-index-000001/_doc/1
{
"long_num": "5", (1)
"long_text": "foo" (2)
}
1、long_num 被映射为 long
2、long_text 使用默认的string映射
path_match and path_unmatch:
path_match和path_unmatch参数的工作方式与match和unmatch相同,但操作方式是指向字段的完整虚线路径,而不仅仅是最终名称,例如some_object.*.some_field。
此示例将名称对象中任何字段的值复制到顶级full_name字段,middle字段除外:
PUT my-index-000001
{
"mappings": {
"dynamic_templates": [
{
"full_name": {
"path_match": "name.*",
"path_unmatch": "*.middle",
"mapping": {
"type": "text",
"copy_to": "full_name"
}
}
}
]
}
}
PUT my-index-000001/_doc/1
{
"name": {
"first": "John",
"middle": "Winston",
"last": "Lennon"
}
}
请注意,除了leaf 字段之外,path_match和path_unmatch参数在对象路径上也匹配。例如,为以下文档编制索引将导致错误,因为“路径匹配”设置还与对象字段name.title匹配,该字段不能映射为文本:
PUT my-index-000001/_doc/2
{
"name": {
"first": "Paul",
"last": "McCartney",
"title": {
"value": "Sir",
"category": "order of chivalry"
}
}
}
Template variables
{name}和{dynamic_type}占位符在映射中被替换为字段名和检测到的动态类型。以下示例将所有字符串字段设置为使用与字段同名的分析器,并禁用所有非字符串字段的doc_values:
PUT my-index-000001
{
"mappings": {
"dynamic_templates": [
{
"named_analyzers": {
"match_mapping_type": "string",
"match": "*",
"mapping": {
"type": "text",
"analyzer": "{name}"
}
}
},
{
"no_doc_values": {
"match_mapping_type":"*",
"mapping": {
"type": "{dynamic_type}",
"doc_values": false
}
}
}
]
}
}
PUT my-index-000001/_doc/1
{
"english": "Some English text", (1)
"count": 5 (2)
}
1、英语字段被映射为英语分析器的字符串字段。
2、count 字段映射long字段在禁用doc_values的时候。
动态模板例子:
以下是一些可能有用的动态模板示例:
结构化搜索:
设置“dynamic”:“true”时,Elasticsearch将字符串字段映射为带有关键字子字段的文本字段。如果我们只为结构化内容编制索引,而对全文搜索不感兴趣,则可以使Elasticsearch仅将字段映射为关键字字段。但是,我们必须搜索与搜索这些字段所索引的值完全相同的值。
PUT my-index-000001
{
"mappings": {
"dynamic_templates": [
{
"strings_as_keywords": {
"match_mapping_type": "string",
"mapping": {
"type": "keyword"
}
}
}
]
}
}
字符串的纯文本映射:
与上一个示例相反,如果我们只关心字符串字段的全文搜索,而不打算运行聚合、排序或精确搜索,则可以指示Elasticsearch将字符串映射为文本:
PUT my-index-000001
{
"mappings": {
"dynamic_templates": [
{
"strings_as_text": {
"match_mapping_type": "string",
"mapping": {
"type": "text"
}
}
}
]
}
}
或者,我们可以创建动态模板,将字符串字段映射为映射的运行时部分中的keyword字段。当Elasticsearch检测到string类型的新字段时,这些字段将创建为keyword类型的运行时字段。
虽然我们的string字段不会被编入索引,但它们的值存储在_source中,可以用于搜索请求、聚合、筛选和排序。
例如,以下请求创建一个动态模板,将string字段映射为keyword类型的运行时字段。虽然运行时定义为空,但新srting 字段被映射为keyword运行时字段是基于动态映射规则让Elasticsearch使用新增字段类型去映射。任何未通过日期检测或数字检测的字符串将自动映射为keyword:
PUT my-index-000001
{
"mappings": {
"dynamic_templates": [
{
"strings_as_keywords": {
"match_mapping_type": "string",
"runtime": {}
}
}
]
}
}
索引一个简单的文档:
PUT my-index-000001/_doc/1
{
"english": "Some English text",
"count": 5
}
查看映射时,我们将看到english字段是一个运行时字段,其类型为关键字:
GET my-index-000001/_mapping
{
"my-index-000001" : {
"mappings" : {
"dynamic_templates" : [
{
"strings_as_keywords" : {
"match_mapping_type" : "string",
"runtime" : { }
}
}
],
"runtime" : {
"english" : {
"type" : "keyword"
}
},
"properties" : {
"count" : {
"type" : "long"
}
}
}
}
}
关闭norms:
norms 是指数时间评分因子。如果我们不关心评分(例如,如果我们从不按评分对文档排序),则可以禁用索引中这些评分因子的存储并节省一些空间。
PUT my-index-000001
{
"mappings": {
"dynamic_templates": [
{
"strings_as_keywords": {
"match_mapping_type": "string",
"mapping": {
"type": "text",
"norms": false,
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
]
}
}
此模板中显示的子关键字字段与动态映射的默认规则一致。当然,如果我们不需要它们,因为我们不需要在此字段上执行精确的搜索或聚合,可以按照上一节中的描述将其删除。
时间序列(Time series)
在使用Elasticsearch进行时间序列分析时,通常会有许多数字字段,我们通常会对这些字段进行聚合,但从不进行筛选。在这种情况下,我们可以禁用对这些字段的索引以节省磁盘空间,还可以获得一些索引速度:
PUT my-index-000001
{
"mappings": {
"dynamic_templates": [
{
"unindexed_longs": {
"match_mapping_type": "long",
"mapping": {
"type": "long",
"index": false
}
}
},
{
"unindexed_doubles": {
"match_mapping_type": "double",
"mapping": {
"type": "float", (1)
"index": false
}
}
}
]
}
}
1、与默认的动态映射规则一样,double映射为float,这通常足够精确,但需要一半的磁盘空间。