Elasticsearch:Dynamic mapping
【腾讯云 Elasticsearch Service】高可用,可伸缩,云端全托管。集成X-Pack高级特性,适用日志分析/企业搜索/BI分析等场景
Elasticsearch 最重要的功能之一是它试图摆脱你的方式,让你尽快开始探索你的数据。 要索引文档,你不必首先创建索引,定义映射类型和定义字段 - 你只需索引文档,那么 index,type 和 field 将自动生效。比如:
PUT data/_doc/1 { "count": 5 }
上面的命令将自动帮我们生成一个叫做 data 的 index,并同时生成一个叫做 _doc 的 type 及一个叫做 count 的 field。count 的数据类型是 long。这个非常方便,它不像传统的 RDMS 那样,先要创建一个数据库,让后一个 table,然后才可以向 table 里写入数据。
自动检测和添加新字段称为动态映射。 动态映射规则可以根据您的目的进行定制:
在今天的这篇文章中,我们来分别介绍这两个方面的内容。
动态模板
假设您有包含大量字段的文档
- 或者在映射定义时未知的动态字段名称的文档
- 和 nested 的 key/value 对不是一个很好的解决方案
使用动态模板,您可以基于定义字段的映射
- 字段的数据类型, 使用
match_mapping_type
- 字段的名字,使用
match
andunmatch
或match_pattern
. - 或者字段的路径,使用
path_match
及path_unmatch
.
动态模板由命名对象的数组来定义的:
"dynamic_templates": [ { "my_template_name": { (1) ... match conditions ... (2) "mapping": { ... } (3) } }, ... ]
- template 的名字可以是任何一个字符串
- 匹配的条件可以是这里的任何一种
match_mapping_type
,match
,match_pattern
,unmatch
,path_match
,path_unmatch
- 被匹配的字段的 mapping
例如,如果我们想要将所有整数字段映射为整数而不是 long,并将所有字符串字段映射为 text 和 keyword,我们可以使用以下模板:
PUT my_index{ "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/_doc/1{ "my_integer": 5, "my_string": "Some string" }
通过上面的动态 template 映射,我们可以看到 my_integer 被映射为 integer 而不是 long。my_string 是一个 multi_field 字段。
假设你希望任何未映射的字符串字段默认情况下映射为 “keyword” 类型,那么我们可以这么定义:
PUT test2{ "mappings": { "dynamic_templates": [ { "my_string_fields": { "match_mapping_type": "string", "mapping": { "type": "keyword" } } } ] }}
match 及 unmatch
match 参数使用模式匹配字段名称,而 unmatch 使用模式排除匹配匹配的字段。
以下示例匹配名称以 long_ 开头的所有字符串字段(以_text结尾的字符串除外)并将它们映射为长字段:
PUT my_index{ "mappings": { "dynamic_templates": [ { "longs_as_strings": { "match_mapping_type": "string", "match": "long_*", "unmatch": "*_text", "mapping": { "type": "long" } } } ] }} PUT my_index/_doc/1{ "long_num": "5", "long_text": "foo" }
我们可以通过如下的命令来查看它们的数据类型:
GET my_index/_mapping
显示的结果为:
{ "my_index" : { "mappings" : { "dynamic_templates" : [ { "longs_as_strings" : { "match" : "long_*", "unmatch" : "*_text", "match_mapping_type" : "string", "mapping" : { "type" : "long" } } } ], "properties" : { "long_num" : { "type" : "long" }, "long_text" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } } } } }}
从上面,我们可以看出来,long_num 的数据类型是 long,而 long_text 的数据类型是 text。
控制动态字段
默认情况下,当在文档中找到以前未见过的字段时,Elasticsearch 会将新字段添加到类型映射中。 通过将 dynamic 参数设置为 false(忽略新字段)或 strict(如果遇到未知字段则抛出异常),可以在文档和对象级别禁用此行为。
在生产(product) 环境中,你极有可能会创建你的 mapping 在索引你的数据之前,而且你极有可能不想你的 mapping 会被修改:
POST blogs/_doc/2{ "some_new_field": "What should we do?" }
在通常的情况下,上面的一个命令可能会自动帮我们在 blogs 索引里增加一个新的叫做 some_new_field 的字段。
你可以使用 “dynamic” 属性(三个选项)控制添加到映射的新字段的效果:
doc indexed? |
fields indexed? |
mapping updated? |
|
---|---|---|---|
true |
Yes |
Yes |
Yes |
false |
Yes |
No |
No |
strict |
No |
上面的表格显示,当一个新的字段被添加到一个索引中,并且这个字段之前没有在 mapping 中定义:
- 在 dynamic 为 true 时,这个文档将被建立索引,从而新增加的字段将是可以被搜索及应用于聚合,mapping 也会自动更新
- 在 dynamic 为 false 时,这个文档将被建立索引,但是新的字段将不被建立索引,mapping 将不被更新(包含新的的字段的mapping)
- 在 dynamic 为 strict 时,这个文件将不被建立索引
PUT blogs_example/_mapping{ "dynamic": "strict"}
在上面我们在 mapping 中加入了 dynamic,并且设置为 strict,它表明如果现有的 mapping 里没有定义这个字段,那么就不 index 这个文档。
PUT /blogs_example/_doc/1{ "new_field": "this is a new field"}
如果new_field从来没有在mapping中定义过,那么,上面的命令会出现如下的错误:
{ "error": { "root_cause": [ { "type": "strict_dynamic_mapping_exception", "reason": "mapping set to strict, dynamic introduction of [new_field] within [_doc] is not allowed" } ], "type": "strict_dynamic_mapping_exception", "reason": "mapping set to strict, dynamic introduction of [new_field] within [_doc] is not allowed" }, "status": 400}
如果这个问题出现了,我们必须修改我们现有的 index 的 mapping:
PUT blogs_example/_mapping{ "properties": { "new_field": { "type": "text" } }}
那么重新运行之前的那个命令就可以了。
settings 以防止映射爆炸
在索引中定义太多字段是一种可能导致映射爆炸的情况,这可能导致内存不足错误和难以恢复的情况。 这个问题可能比预期更常见。 例如,考虑插入的每个新文档引入新字段的情况。 这在动态映射中非常常见。 每次文档包含新字段时,这些字段最终都会出现在索引的映射中。 这并不需要担心少量数据,但随着映射的增加,它可能会成为一个问题。 以下设置允许您限制可手动或动态创建的字段映射的数量,以防止错误的文档导致映射爆炸:
index.mapping.total_fields.limit
索引中的最大字段数。 字段和对象映射以及字段别名都计入此限制。 默认值为1000
index.mapping.depth.limit
字段的最大深度,以内部对象的数量来衡量。 例如,如果所有字段都在根对象级别定义,则深度为1.如果有一个对象映射,则深度为2,等等。默认值为20。
index.mapping.nested_fields.limit
索引中不同 nested 映射的最大数量,默认为50。
index.mapping.nested_objects.limit
所有 nested 类型中单个文档中嵌套 JSON 对象的最大数量,默认为10000。
index.mapping.field_name_length.limit
设置字段名称的最大长度。 默认值为 Long.MAX_VALUE(无限制)。 此设置实际上不是解决映射爆炸的问题,但如果要限制字段长度,则可能仍然有用。 通常不需要设置此设置。 默认是可以的,除非用户开始添加大量具有真正长名称的字段。
上面的字段都可以在一个 index 的设置中进行设置,比如:
PUT test_blog { "settings": { "index.mapping.total_fields.limit": 2000, "number_of_replicas": 0, "number_of_shards": 1 }}
最新活动
包含文章发布时段最新活动,前往ES产品介绍页,可查找ES当前活动统一入口
Elasticsearch Service自建迁移特惠政策>>
Elasticsearch Service 新用户特惠狂欢,最低4折首购优惠 >>
Elasticsearch Service 企业首购特惠,助力企业复工复产>>
关注“腾讯云大数据”公众号,技术交流、最新活动、服务专享一站Get~
- RxJava2 实战(1) - 后台执行耗时操作,实时通知 UI 更新
- AutoIt木马又一发:暗藏神秘照片
- css3动画从入门到精通
- ReactJs和React Native的那些事
- Linux学习-文件排序和FASTA文件操作
- Bash漏洞再次演进:缓冲区溢出导致远程任意命令执行
- Pandas,让Python像R一样处理数据,但快
- ViewPager 实现 Galler 效果, 中间大图显示,两边小图展示
- 最小生成树-Prim算法和Kruskal算法
- Bash漏洞批量检测工具与修复方案
- 组合模式
- 用Fiddler在Android上抓包(Http+https)
- Architecture Components ViewModel的控制。
- React Native之AppRegistry模块
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法