- Elastic Stack应用宝典
- 田雪松编著
- 2694字
- 2025-02-27 02:18:28
3.2 动态映射与索引模板
索引并非一定要先创建才能存储文档,可以在不创建索引的情况下直接向索引中添加文档。Elasticsearch的动态映射机制会根据文档内容,并依据索引模板自动创建一个与文档相匹配的索引。如果不希望Elasticsearch自动创建索引,可以通过在elasticsearch.yml配置文件中将action.auto_create_index参数设置为false来禁止。这个参数还可以接收“+shop_*,-user_*”这种形式的值,其中加号“+”代表允许自动创建索引,而减号“-”则代表不允许。所以“+shop_*,-user_*”的意思就是允许以“shop_”开头的索引自动创建,而不允许“user_”开头的索引自动创建。此外,_cluster接口也提供了动态修改这个配置的方法:

示例3-12 禁用动态创建索引
动态映射依赖一些预定义的动态字段类型映射规则,同时还可以使用动态字段模板自定义字段类型映射。如果希望在创建索引时自动应用某些配置信息,可使用索引模板定义创建索引时默认添加的别名、配置和映射关系。
3.2.1 动态字段
即使在索引创建后,Elasticsearch依然支持向索引中增加新字段,这种动态增加字段的特性可通过dynamic参数来修改。dynamic参数可以设置在映射类型上,或是对象类型的字段上,可选值为true、false和strict,默认值为true。当dynamic设置为false时,新添加的字段将会被忽略;而设置为strict时则会抛出异常。例如在示例3-13中将动态添加字段功能关闭了,所有未在properties中定义的新字段都将被忽略:


示例3-13 dynamic参数
需要注意的是,当dynamic设置为false,在添加新文档时出现的新字段依然会被保存到文档中,只是这个字段的定义并不会被添加到索引映射的字段定义中。只有当dynamic为true时,新添加字段才会按一定的数据类型映射规则,将它们添加到索引映射的定义中。表3-3列出了从JSON类型到Elasticsearch字段类型的对应关系:
表3-3 字段类型映射

如果字符串中含有日期或数值,它们可以被解析为date或numeric类型。Elasticsearch默认对含有日期的字符串会自动解析为date类型,可以通过将映射类型的date_detection参数设置为false关闭解析。日期字符串在解析时使用的格式可通过dynamic_date_formats设置,默认值为 ["strict_date_optional_time","yyyy/MM/dd HH:mm:ss Z‖yyyy/MM/dd Z"]。含有数值的字符串默认不会被解析为数值类型,但可通过numeric_detection参数开启数值解析。
3.2.2 动态模板
动态模板(Dynamic Template)用于自定义动态添加字段时的映射规则,可通过索引映射类型的dynamic_templates参数设置。该参数接收一组命名的动态模板,每一个模板由匹配条件和映射规则组成。匹配条件定义了新字段是否可以使用当前模板,可根据新字段的数据类型、名称和路径来定义条件;而映射规则由参数mapping定义,它需要给出新字段要使用哪些参数,可使用type定义新字段数据类型,也可以使用第2章2.2.3节中表2-2给出的适用参数设置新字段其他特性。
匹配规则可使用关键字match_mapping_type匹配新字段数据类型,这可以用于将一种默认类型转换为其他类型或者设置其他特性。比如,JSON整型默认会被映射为long,如果希望将整型映射为integer可以按示例3-14的方式定义:


示例3-14 match_mapping_type
在示例3-14中,不仅将整型设置为integer类型,还将它的文档值机制关闭,即将doc_values参数设置为false。除了匹配新字段的数据类型,还可使用match、match_pattern和unmatch匹配新字段名称。其中match和unmatch可以使用星号“*”做名称匹配,而match_pattern则支持正则表达式。匹配新字段路径可使用path_match和path_unmatch,路径与名称的区别是其中包含点“.”。在mapping参数中,还可以使用{name}和{dynamic_type}代表新字段名称和类型。例如在示例3-15中keep_original动态模板将所有以“original_”开头字段的数据类型设置为原始类型:


示例3-15 使用{dynamic_type}
需要注意的是,如果一个字段同时满足两个动态模板,它最终会应用在动态模板中先定义的那个规则。例如在示例3-15中,如果新添加字段名为“original_age”且类型为long,那么它就同时满足keep_original和to_integer两个模板,但它最终会应用第一个模板keep_original,因为这个模板是先定义的。
3.2.3 索引模板
索引模板(Index Template)与动态模板不是一个概念,动态模板定义了索引创建后新添加字段的映射规则,而索引模板是在创建索引时默认为索引添加的别名、配置和映射等信息。索引模板包含该模板适用索引的模式或规则,以及索引创建时默认包含的别名、配置和映射关系等。它们分别通过index_patterns、aliases、settings和mappings等四个参数设置,可通过_template接口创建。例如在示例3-16中创建了一个名为user_tpl的索引模板:

示例3-16 创建索引模板
在示例3-16中,使用PUT方法请求的路径中,_template为索引模板接口的关键字,而后接的user_tpl则是模板名称。index_patterns参数定义了模板适用于名称以user或employee开头的索引,如果index_patterns在定义时出现规则重叠,索引创建时就有可能与多个模板匹配。比如定义一个匹配模式为“*”的模板all_tpl,那么当创建users索引时all_tpl和user_tpl就都满足匹配模式。Elasticsearch在处理这种冲突时,会将所有模板合并应用到索引上,这会导致后应用的模板规则覆盖先应用的模板规则。所以,索引模板提供了一个参数order用于指定合并应用的次序,如果不指定则order值为0。
aliases定义了默认将创建的索引别名,示例3-16创建了一个{index}_by_gender的别名,其中{index}是一个占位符,索引创建时将取索引实际名称替换。settings字段定义了默认配置,而mappings则定义了默认字段信息。在定义好这个模板后可通过“PUT users”请求创建索引,然后通过“GET users”查看索引信息会发现模板中预定义的别名、字段都出现在了索引的设置中。需要注意的是,模板仅在索引创建时起作用,更改模板不会对已经创建的索引起作用。
_template接口也可以通过GET、DELETE和HEAD方法请求,分别用于对模板的查看、删除及存在性校验。此外,如果想要查看所有的模板,可以使用CAT接口,具体请求如下:

示例3-17 _template接口
索引模板在Logstash和Beats组件向Elasticsearch传输数据时非常有用,它们基本上都会根据自身对索引的要求创建索引模板。有关这两个组件的介绍请参考本书后续章节。
3.2.4 _mapping接口
索引的映射关系在索引创建后可通过_mapping接口查看或修改,可以访问该接口的请求方法包括GET、POST和PUT。使用GET方法访问时可以查看索引的映射类型及字段,请求资源的路径基本格式为“/<索引>/_mapping/<映射类型>/field/<字段>”。其中,_mapping为接口关键字必须使用,其余为可选项。如果没有指定索引名称而直接调用GET _mapping,将返回所有索引的映射关系。如果指定了索引名称则查看该索引的映射关系,指定了映射类型或字段则查看它们的映射关系。例如在示例3-18中,第一个请求查看students索引的映射关系,而第二个请求则只查看其中的gender属性:

示例3-18 查看映射关系
使用PUT或POST方法请求_mapping接口时,可以向索引更新或添加新字段,或修改已有字段的某些配置。例如在示例3-19的请求中,向students添加了age属性:

示例3-19 更新映射
在这种请求中,索引可以指定一个或多个。对已存在的映射关系只能添加字段或多类型,但字段一旦创建就不能删除。如果一定要删除某一字段,惟一的办法是删除原索引后添加不包含该字段的新索引,然后再将原索引中的数据导入到新索引中做reindex。除了不能删除字段以外,字段的多数参数也不能修改,惟一可修改的参数是ignore_above。修改字段的方式与示例3-19一致,将要修改的参数放在字段配置中即可。
由此可见,在设计索引时一定要做好规划,在初始时可以只加入必要字段。为了隔离索引变化对用户的影响,可以只提供索引别名给用户访问,当索引发生变化时只要把别名分配到新索引就可以了。