1. Index Templates 相关阅读:https://www.elastic.co/guide/en/elasticsearch/reference/7.4/indices-templates.html
Index Templates 会帮助你设定 Mappings 和 Settings,并按照一定的规则自动匹配到新创建的索引上。其符合如下几点规则:
模板仅在一个索引被新创建时才会产生作用,修改模板不会影响已创建的索引; 可以设定多个索引模板,符合指定规则的索引会将模板进行 “merge”,其中模板所指定的 order 可以控制模板的合并顺序,order 值较大者的会覆盖较小者。 应用创建索引时,用户所指定的 Settings 和 Mappings 会覆盖之前模板中的设定。 下面通过例子来讲解下。首先我们创建索引 mytemplate,具体如下所示:
1 2 3 4 5 PUT mytemplate/_doc/1 { "someNumber" :"1" , "someDate" :"2019/01/01" }
由于 ElasticSearch 默认支持对符合日期类型的字段自动转为 date 类型,所以 someDate 字段不是 text 类型,而是 date 类型:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 GET mytemplate/_mapping // 结果 { "mytemplate" : { "mappings" : { "properties" : { "someDate" : { "type" : "date" , "format" : "yyyy/MM/dd HH:mm:ss||yyyy/MM/dd||epoch_millis" }, "someNumber" : { "type" : "text" , "fields" : { "keyword" : { "type" : "keyword" , "ignore_above" : 256 } } } } } } }
下面我们创建一个默认 Index Template,由于 index_patterns 字段设置的正则规则默认匹配所有索引,索引后续新创建的索引都会按照 template_default 模板来设置对应的 settings:
1 2 3 4 5 6 7 8 9 10 PUT _template/template_default { "index_patterns": ["*"], // 适用所有索引 "order" : 0, "version": 1, "settings": { "number_of_shards": 1, // 设置一个分片 "number_of_replicas": 2 // 设置两个副本分片 } }
例如下面添加一个索引,然后查询其 settings:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 PUT new_index/_doc/1 { "someNumber" :"1" , "someDate" :"2019/01/01" } GET new_index/_settings // 结果 { "new_index" : { "settings" : { "index" : { "creation_date" : "1673272193840" , "number_of_shards" : "1", // 一个分片 "number_of_replicas" : "2", // 两个副本分片 "uuid" : "cAZapaEtQ9Own7YCyR8kWQ", "version" : { "created" : "7040299" }, "provided_name" : "new_index" } } } }
我们再创建一个模板,该模板仅匹配名称以 test 开头的索引。需要说明的是由于 template_test 指定的 order 为 1,所以后续创建的以 test 开头的索引将会使用到 template_test 模板,其中 number_of_replicas 将会覆盖为 3。另外 date_detection 由于设置为 false,将不再支持对符合日期规则的 text 文本转为 date 类型。由于 numeric_detection 设置为 true,将会对 text 类型的数值转为 long 类型数值。
1 2 3 4 5 6 7 8 9 10 11 12 13 PUT /_template/template_test { "index_patterns" : ["test*" ], "order" : 1 , "settings" : { "number_of_shards" : 1 , "number_of_replicas" : 3 }, "mappings" : { "date_detection": false, // 日期格式检测,默认开启,会将字符串日期转成 date 类型 "numeric_detection": true // 数值检测,默认关闭,会将字符串数值转为数值 } }
如下我们添加一个索引,并查询其 mapping 和 setting 值:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 PUT test_index/_doc/1 { "someNumber" :"1" , "someDate" :"2019/01/01" } GET test_index/_mapping // 响应 { "test_index" : { "mappings" : { "date_detection" : false , "numeric_detection" : true , "properties" : { "someDate" : { // 不再是 date 类型 "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } }, "someNumber" : { "type" : "long" // 转为 long 类型 } } } } } GET test_index/_settings // 响应 { "test_index" : { "settings" : { "index" : { "creation_date" : "1673272800166" , "number_of_shards" : "1" , "number_of_replicas" : "3", // 三个副本分片 "uuid" : "Q__3CZOwR_yuTtrBL206vw", "version" : { "created" : "7040299" }, "provided_name" : "test_index" } } } }
下面我们再显式设置索引的 testmy 的 settings,虽然其匹配 template_test 模板,但是显式指定的 settings 会覆盖模板中的设定:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 PUT testmy { "settings" :{ "number_of_replicas" :5 } } // settings { "testmy" : { "settings" : { "index" : { "creation_date" : "1673273008702" , "number_of_shards" : "1" , "number_of_replicas" : "5" , "uuid" : "6twmxOU_Q76NvAgEUrEIHw" , "version" : { "created" : "7040299" }, "provided_name" : "testmy" } } } }
2. Dynamic Templates 相关阅读:https://www.elastic.co/guide/en/elasticsearch/reference/7.4/dynamic-mapping.html
Dynamic Templates 根据 ElasticSearch 识别的数据类型结合字段名称匹配规则来动态设定字段类型,例如将所有的字符串类型都设定为 keyword 类型,或将 is 开头的字段都设置成 boolean 类型等。
下面我们添加一个文档,默认情况下 firstName 和 isVIP 都是 text 类型,且都含有 keyword 类型子字段,mappings 结果如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 PUT my_index/_doc/1 { "firstName" :"Ruan" , "isVIP" :"true" } // mappings 结果 { "my_index" : { "mappings" : { "properties" : { "firstName" : { "type" : "text" , "fields" : { "keyword" : { "type" : "keyword" , "ignore_above" : 256 } } }, "isVIP" : { "type" : "text" , "fields" : { "keyword" : { "type" : "keyword" , "ignore_above" : 256 } } } } } } }
我们为索引 my_index 添加一个 Dynamic Templates,规则如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 PUT my_index { "mappings" : { "dynamic_templates" : [ { "strings_as_boolean": { // strings_as_boolean 模板名称 "match_mapping_type": "string", // 匹配的字段需要是字符串类型 "match":"is*", // 匹配的字段名称需要以 is 开头 "mapping": { // 匹配的字段会被映射成 boolean 类型 "type": "boolean" } } }, { "strings_as_keywords" : { "match_mapping_type" : "string" , "mapping" : { "type" : "keyword" } } } ] } }
同理我们再添加一个文档试试,并查询其 mappings:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 PUT my_index/_doc/1 { "firstName" :"Ruan" , "isVIP" :"true" } // mappings { "my_index" : { "mappings" : { "dynamic_templates" : [ { "strings_as_boolean" : { "match" : "is*" , "match_mapping_type" : "string" , "mapping" : { "type" : "boolean" } } }, { "strings_as_keywords" : { "match_mapping_type" : "string" , "mapping" : { "type" : "keyword" } } } ], "properties" : { "firstName" : { "type" : "keyword" // firstName 是 keyword 类型 }, "isVIP" : { "type" : "boolean" // isVIP 则是 boolean 类型 } } } } }
再举一个示例,如下我们创建一个名称为 dynamic_templates 的模板,其支持将 name 下面的字段和不包含 middle 的字段拷贝出来作为新的字段 full_name:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 PUT my_index { "mappings" : { "dynamic_templates" : [ { "full_name" : { "path_match" : "name.*" , "path_unmatch" : "*.middle" , "mapping" : { "type" : "text" , "copy_to" : "full_name" } } } ] } }
我们添加对应的索引,可以发现可以通过 name 下面的 first 字段的值 John 检索到文档,而无法通过 middle 字段的值 Winston 检索得到:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 PUT my_index/_doc/1 { "name" : { "first" : "John" , "middle" : "Winston" , "last" : "Lennon" } } // 如下检索得到文档 GET my_index/_search { "query" : { "match" : { "full_name" : "John" } } } // 如下检索不到文档 GET my_index/_search { "query" : { "match" : { "full_name" : "Winston" } } }