文章目录
ElasticSearch映射(一)
映射是定义文档以及其包含的字段如果存储和索引的过程。
每个文档中的字段集合都有他们自己的数据类型。当你在映射数据的时候,你需要创建一个包含与文档相关的字段列表的映射定义。一个数据映射定义也可以包含元数据字段,例如_source
字段,用于自定义处理文档相关的元数据。
你可以使用动态映射后者明确的映射来定义你的数据。每种方式都有他自己独特的好处。明确定义映你可以在字段上不使用默认值,或者你可以更好的控制创建哪些字段。然后你也可以让ElasticSearch来动态添加字段。
动态映射
动态字段映射
当ElasticSearch检测文档中出现了一个新的字段,它将会动态的为这个字段映射默认的数据类型。dynamic
参数控制着这样的行为。
你可以通过设置dynamic
参数的true
或者runtime
来明确的告诉ElasticSearch基于传入的文档来动态的创建字段。当动态字段映射开启的时候,ElasticSearch根据以下表格中的规则来决定怎么对每个字段进行映射数据类型。
JSON data type | "dynamic":"true" | "dynamic":"runtime" |
---|---|---|
null | 不添加字段 | 不添加字段 |
true or false | boolean | boolean |
double | float | double |
integer | long | long |
object 1 | object | object |
array | 取决于数组中的第一个非空值 | 取决于数组中的第一个非空值 |
string that passes date detection | date | date |
string that passes numeric detection | float or long | double or long |
string that doesn’t pass date detection or numeric detection | text with a .keyword sub-field | keyword |
你也可以在文档和对象级别关闭动态映射,设置dynamic
为false
来忽略新的字段。如果ElasticSearch遇到新的字段,则strict
拒绝这个文档。
提示:可以使用update mapping API来动态设置已经存在的字段
你可以动态的自定义日期检测和数值检测的字段映射规则,要自定义适用于其他动态字段,您可以使用dynamic templdate
。
日期检测
如果date_detection
开启了(默认值),新的string字段会被检查它的内容是否与dynamic_date_formats
中指定的任何日期格式相匹配,如果匹配,将添加相应格式的日期字段。
dynamic_date_formats
的默认值为:
[ "strict_date_optional_time","yyyy/MM/dd HH:mm:ss Z||yyyy/MM/dd Z"]
例如:
curl -X PUT "localhost:9200/my-index-000001/_doc/1?pretty" -H 'Content-Type: application/json' -d'
{
"create_date": "2015/09/02"
}'
curl -X GET "localhost:9200/my-index-000001/_mapping?pretty"
关闭日期检测
通过设置date_detection
为false
可以关闭日期检测:
curl -X PUT "localhost:9200/my-index-000001?pretty" -H 'Content-Type: application/json' -d'
{
"mappings": {
"date_detection": false
}
}'
curl -X PUT "localhost:9200/my-index-000001/_doc/1?pretty" -H 'Content-Type: application/json' -d'
{
"create": "2015/09/02"
}'
自定义日期检测格式
或者,dynamci_date_formats
支持在你自己的date fomarts
中自定义日期检测格式:
curl -X PUT "localhost:9200/my-index-000001?pretty" -H 'Content-Type: application/json' -d'
{
"mappings": {
"dynamic_date_formats": ["MM/dd/yyyy"]
}
}'
curl -X PUT "localhost:9200/my-index-000001/_doc/1?pretty" -H 'Content-Type: application/json' -d'
{
"create_date": "09/25/2015"
}'
数值检测
虽然 JSON 支持原生浮点和整数数据类型,但某些应用程序或语言有时可能会将数字呈现为字符串。通常正确的解决方案是显式映射这些字段,所以可以启用数字检测(默认情况下禁用)以自动执行此操作:
PUT my-index-000001
{
"mappings": {
"numeric_detection": true
}
}
PUT my-index-000001/_doc/1{ "my_float": "1.0", "my_integer": "1" }
动态模板
动态模板可以在默认字段映射规则之外更好的控制ElasticSearch如果映射你的数字段。你可以设置动态字段映射参数为true
或者runtime
来开启动态字段映射。你也可以使用动态模板来自定义映射,动态模板映射基于匹配条件应用于动态添加的字段
match_mapping_type
:对ElasticSearch检测到的数据类型进行操作。match
和unmatch
:使用模式匹配来匹配字段名称path_mathc
和path_unmatch
:对完整路径上的所有字段进行操作。- 如果动态模板没有定义
match_mapping_type、match、unmatch、path_mathc、path_unmatch
任何一个,它将不会匹配任何字段,您仍然可以在大批量请求的dynamic_template
部分按名称引用模板。
使用映射规范中的{name}
和{dynamic_type}
模板变量作为占位符
提示:动态值字段映射只有当一个字段值包含有效值(not null或者空数组)才会被增加。如果not_value
在dynamic_tamplate
中被使用,它只会在第一个具有该字段具体值的文档被索引后被应用
动态模板被命名为一个对象数组:
"dynamic_templates": [ { "my_template_name": { ... match conditions ... "mapping": { ... } } }, ... ]
验证动态模板
如果提供的映射包含无效的映射片段,将会返回验证错误。发生在索引时或者大多数情况下动态索引被更新的时候会验证动态索引模板。提供无效的映射片段时可能导致更新或者验证动态模板失败:
- 如果动态模板中没有配置
match_mapping_type
,但是模板对至少一种预定义的映射片段有效,则映射片段被视为有效。然而如果与动态模板匹配的的字段被索引为不同的类型,则在索引时返回验证错误。例如没有配置match_mapping_type
的动态模板字符串类型是有效的,但是如果动态模板匹配到的字段为索引为Long
,则在索引的时候会返回异常。建议在索引片段上将match_mapping_type
设置为预期的JSON类型或者配置成想要的类型。 - 如果
{name}
占位符被使用在映射片段中,当更新动态索引模板的时候会跳过验证,这是因为在这个时候字段名字还未知。验证发生在索引时候模板被应用的时候。
模板按顺序进行处理—第一个匹配到的模板获胜。当通过update mapping API来put一个新的动态模板,已存在的模板将会被覆盖。这允许动态模板在最初添加后重新排序或删除。
在动态模板中映射运行时字段
如果希望ElasticSearch将某种类型的新字段映射为运行时字段,需要在索引映射中设置"dynamic":"runtime"
。这些字段不会加入索引中,在查询中从_source
字段中加载。
或者你可以使用默认的动态模板规则,并创建动态模板将特定的字段映射为运行时字段。在你的索引映射中设置"dynamic":"true"
,然后创建一个动态模板将特定的类型的新字段映射成运行是字段。
假设您有数据其中每个字段都是以_ip
开头。基于动态映射,ElasticSearch会将检测到的字符串映射为浮点数或者长整数。但是你可以创建一个动态模板,将新字符串映射为ip
类型的运行时字段。
根据请求定义一个名字为string_as_ip
的动态模板。当ElasticSearch检测一个新的string
类型的新字段匹配ip*
模式,它将这些字段映射成ip
类型的运行时字段。因为ip
字段没有被动态的映射,因此您可以将此模板与 "dynamic":"true"
或 "dynamic":"runtime"
一起使用:
curl -X PUT "localhost:9200/my-index-000001/?pretty" -H 'Content-Type: application/json' -d'{ "mappings": { "dynamic_templates": [ { "strings_as_ip": { "match_mapping_type": "string", "match": "ip*", "runtime": { "type": "ip" } } } ] }}'
match_mapping_type
match_mapping_type
是有JSON解析器检测的数据类型。因为JSON解析器不区分long、integer
或者double、float
,他总是选择最宽泛的数据类型,例如long
作为整数,double
作为浮点数。
ElasticSearch自动检测以下数据类型:
JSON data type | "dynamic":"true" | "dynamic":"runtime" |
---|---|---|
null | No field added | No field added |
true or false | boolean | boolean |
double | float | double |
integer | long | long |
object 1 | object | object |
array | Depends on the first non-null value in the array | Depends on the first non-null value in the array |
string that passes date detection | date | date |
string that passes numeric detection | float or long | double or long |
string that doesn’t pass date detection or numeric detection | text with a .keyword sub-field | keyword |
使用(*)
可以匹配任意数据类型
例如,我们希望所有的integer
字段映射为integer
而不是long
,所有的string
类型映射为text
和keyword
类型,我们可以使用以下动态模板:
curl -X PUT "localhost:9200/my-index-000001?pretty" -H 'Content-Type: application/json' -d'{ "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 } } } } } ] }}'
curl -X PUT "localhost:9200/my-index-000001/_doc/1?pretty" -H 'Content-Type: application/json' -d'{ "my_integer": 5, "my_string": "Some string" }'
match
和unmatch
match
参数在字段名字上进行模式匹配,而unmatch
用模式匹配去排除match
匹配到的字段名称。
match_pattern
参数调整 match
参数的行为以支持完整的 Java 正则表达式匹配字段名称而不是简单的通配符。例如:
"match_pattern": "regex","match": "^profit_\d+$"
以下示例匹配所有以_long
开头的string
类型的字段(_text
结尾的字符串字段除外),并将他们映射为long
类型的字段:
curl -X PUT "localhost:9200/my-index-000001?pretty" -H 'Content-Type: application/json' -d'{ "mappings": { "dynamic_templates": [ { "longs_as_strings": { "match_mapping_type": "string", "match": "long_*", "unmatch": "*_text", "mapping": { "type": "long" } } } ] }}'
curl -X PUT "localhost:9200/my-index-000001/_doc/1?pretty" -H 'Content-Type: application/json' -d'{ "long_num": "5", "long_text": "foo" }'
path_match
和path_unmatch
path_unmatch
参数的工作方式与 match
和 unmatch
相同,但对字段的完整虚线路径进行操作,而不仅仅是最终名称,例如some_object.*.some_field
。
此示例将 name
对象中任何字段的值复制到顶级 full_name
字段,middle字
段除外:
curl -X PUT "localhost:9200/my-index-000001?pretty" -H 'Content-Type: application/json' -d'{ "mappings": { "dynamic_templates": [ { "full_name": { "path_match": "name.*", "path_unmatch": "*.middle", "mapping": { "type": "text", "copy_to": "full_name" } } } ] }}'
curl -X PUT "localhost:9200/my-index-000001/_doc/1?pretty" -H 'Content-Type: application/json' -d'{ "name": { "first": "John", "middle": "Winston", "last": "Lennon" }}'
请注意,path_match
和 path_unmatch
参数除了叶字段外还匹配对象路径。例如,索引以下文档将导致错误,因为 path_match
设置也匹配对象字段 name.title
,它不能映射为文本:
curl -X PUT "localhost:9200/my-index-000001/_doc/2?pretty" -H 'Content-Type: application/json' -d'{ "name": { "first": "Paul", "last": "McCartney", "title": { "value": "Sir", "category": "order of chivalry" } }}'
模板变量
在映射中{name}
和{dynamic_type}
占位符替换为字段名称和检测到的动态类型。以下示例设置所有字符串字段使用与字段名称一样的analyzer
分析器,为所有不是字符串的字段关闭doc_values
:
curl -X PUT "localhost:9200/my-index-000001?pretty" -H 'Content-Type: application/json' -d'{ "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 } } } ] }}'
curl -X PUT "localhost:9200/my-index-000001/_doc/1?pretty" -H 'Content-Type: application/json' -d'{ "english": "Some English text", "count": 5 }'
动态模板示例
结构化检索
如果你设置dynamic
为true
,ElasticSearch会将字符串字段映射成带有keyword
的text
类型的文本字段。如果你只索引结构化的内容而不对全文索引感兴趣,您可以让ElasticSearch将您的字段仅映射成keyword
字段。如果这样的话,那么您必须搜索这些字段的精确值:
curl -X PUT "localhost:9200/my-index-000001?pretty" -H 'Content-Type: application/json' -d'{ "mappings": { "dynamic_templates": [ { "strings_as_keywords": { "match_mapping_type": "string", "mapping": { "type": "keyword" } } } ] }}'
字符串的纯文本映射
与上个示例完全相反,如果只关心在字符串的字段上进行全文检索并且没有计划运行聚合、排序和精确检索,你需要告诉ElasticSearch将字符串映射为text
文本:
curl -X PUT "localhost:9200/my-index-000001?pretty" -H 'Content-Type: application/json' -d'{ "mappings": { "dynamic_templates": [ { "strings_as_text": { "match_mapping_type": "string", "mapping": { "type": "text" } } } ] }}'
或者。你可以创建一个动态映射模板在运行时来映射字符串字段为keyword
类型。当ElasticSearch检测到有新的string
字段时,这些字段将被创建为keyword
类型的运行时字段。
尽管这些string
字段不会被索引,但是他们的值存储在_source
内部字段中,你可以使用检索、聚合、排序、过滤等请求。
例如以下示例,根据请求创建一个动态模板将string
类型的字段映射成keyword
类型的运行时字段,尽管runtime
值定义为空,但是新的string
字段会根据动态映射规则映射成keyword
类型的运行时字段。未通过日期检测和数值检测的string
类型的字段都会被自动映射成keyword
类型。
curl -X PUT "localhost:9200/my-index-000001?pretty" -H 'Content-Type: application/json' -d'{ "mappings": { "dynamic_templates": [ { "strings_as_keywords": { "match_mapping_type": "string", "runtime": {} } } ] }}'
你索引的一个简单的文档:
curl -X PUT "localhost:9200/my-index-000001/_doc/1?pretty" -H 'Content-Type: application/json' -d'{ "english": "Some English text", "count": 5}'
查看映射时,您会看到 english 字段是关键字类型的运行时字段:
{ "my-index-000001" : { "mappings" : { "dynamic_templates" : [ { "strings_as_keywords" : { "match_mapping_type" : "string", "runtime" : { } } } ], "runtime" : { "english" : { "type" : "keyword" } }, "properties" : { "count" : { "type" : "long" } } } }}
禁用norms
norms
是在索引时评分因素,如果你不关心评分,并且从来不按评分排序来检索文档,你可以禁用评分,这样可以节省一些空间。
curl -X PUT "localhost:9200/my-index-000001?pretty" -H 'Content-Type: application/json' -d'{ "mappings": { "dynamic_templates": [ { "strings_as_keywords": { "match_mapping_type": "string", "mapping": { "type": "text", "norms": false, "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } } } } ] }}'
以上将string
类型的字段映射为text
类型的字段,文本检索可以利用字段进行检索,聚合和排序可以利用field.keyword
上进行。
时间序列
在使用Elasticsearch进行时间序列分析时,通常会有许多数值字段,您通常会对这些字段进行聚合,但不会对它们进行过滤。在这种情况下,你可以禁用这些字段的索引,以节省磁盘空间,也可能获得一些索引速度:
curl -X PUT "localhost:9200/my-index-000001?pretty" -H 'Content-Type: application/json' -d'{ "mappings": { "dynamic_templates": [ { "unindexed_longs": { "match_mapping_type": "long", "mapping": { "type": "long", "index": false } } }, { "unindexed_doubles": { "match_mapping_type": "double", "mapping": { "type": "float", "index": false } } } ] }}'
与默认的动态映射规则一样,双精度数被映射为浮点数,这通常足够准确,但需要一半的磁盘空间。
明确映射
您对数据的了解比 Elasticsearch要多,因此虽然动态映射对于开始很有用,但在某些时候您会想要指定自己的显式映射。
您可以在创建索引或者向已存在的索引上添加新字段时创建字段映射。
创建带有明确映射的索引
您可以使用 create index API 通过显式映射创建新索引。
curl -X PUT "localhost:9200/my-index-000001?pretty" -H 'Content-Type: application/json' -d'{ "mappings": { "properties": { "age": { "type": "integer" }, "email": { "type": "keyword" }, "name": { "type": "text" } } }}'
向现有映射添加字段
您可以使用更新映射 API 向现有索引添加一个或多个新字段。
以下示例添加了员工 ID,这是一个索引映射参数值为 false
的关键字字段。这意味着员工 ID
字段的值已存储但未编入索引或可用于搜索。
curl -X PUT "localhost:9200/my-index-000001/_mapping?pretty" -H 'Content-Type: application/json' -d'{ "properties": { "employee-id": { "type": "keyword", "index": false } }}'
查看索引的映射
你可以使用get mapping
API获取存在索引的映射
curl -X GET "localhost:9200/my-index-000001/_mapping?pretty"
API响应
{ "my-index-000001" : { "mappings" : { "properties" : { "age" : { "type" : "integer" }, "email" : { "type" : "keyword" }, "employee-id" : { "type" : "keyword", "index" : false }, "name" : { "type" : "text" } } } }}
查看指定字段的映射
如果你向单独查看一个或者更多字段的映射,你可以使用get mapping
API来查看。
curl -X GET "localhost:9200/my-index-000001/_mapping/field/employee-id?pretty"
响应
{ "my-index-000001" : { "mappings" : { "employee-id" : { "full_name" : "employee-id", "mapping" : { "employee-id" : { "type" : "keyword", "index" : false } } } } }}