索引模板,故名思议,就是创建索引的模板,模板中包含公共的配置(settings)和映射(Mapping),并包含一个简单触发条件,及条件满足时使用该模板创建一个新的索引。
注意:模板只在创建索引时应用。更改模板不会对现有索引产生影响。当使用create index API时,作为create index调用的一部分定义的设置/映射将优先于模板中定义的任何匹配设置/映射。
一个索引模板示例如下:
1PUT _template/template_1 2{ 3 "index_patterns": [“ubi*”], //@1 4 "settings": { //@2 5 "number_of_shards": 1 6 }, 7 "mappings": { //@3 8 "_doc": { 9 "_source": { 10 "enabled": false 11 }, 12 "properties": { 13 "host_name": { 14 "type": "keyword" 15 }, 16 "created_at": { 17 "type": "date", 18 "format": "" 19 } 20 } 21 } 22 } 23}
代码@1:触发条件。
代码@2:索引配置定义。
代码@3:索引映射配置。
上述示例对应的JAVA示例如下:
1public static final void createIndexTemp() { 2 RestHighLevelClient client = EsClient.getClient(); 3 try { 4 PutIndexTemplateRequest request = new PutIndexTemplateRequest("ubi_index_template") 5 List<String> indexPatterns = new ArrayList<String>(); 6 indexPatterns.add("ubi*"); 7 request.patterns(indexPatterns); 8 9 /** mapping */ 10 XContentBuilder jsonBuilder = XContentFactory.jsonBuilder() 11 .startObject() 12 .startObject("_source") 13 .field("enabled", false) 14 .endObject() 15 16 .startObject("properties") 17 .startObject("host_name") 18 .field("type", "keyword") 19 .endObject() 20 .startObject("created_at") 21 .field("type", "date") 22 .field("format", "yyyy-MM-dd HH:mm:ss") 23 .endObject() 24 25 .endObject() 26 .endObject(); 27 28 29 request.mapping("_doc", jsonBuilder); 30 31 Map<String, Object> settings = new HashMap<>(); 32 33 settings.put("number_of_shards", 1); 34 request.settings(settings); 35 36 System.out.println(client.indices().putTemplate(request, RequestOptions.DEFAULT)); 37 38 } catch (Exception e) { 39 // TODO: handle exception 40 } finally { 41 EsClient.close(client); 42 } 43 }
上述索引模板创建好之后,然后在向一个不存在的索引添加文档时,如果能找到合适的模板,则自动创建索引,否则抛出索引不存在,例如:
1public static void index_template() { 2 ElasticsearchTemplate template = new ElasticsearchTemplate(); 3 try { 4 Map<String, String> data = new HashMap<>(); 5 data.put("host_name", "localhost"); 6 data.put("created_at", "2019-04-07 23:05:04"); 7 //ubi_201904该索引一开始不存在,但索引ubi_201904符合ubi_index_template 8 //中定义的匹配表达式ubi*,所以会自动创建索引。 9 template.index("ubi_201904", "_doc", data); 10 } finally { 11 template.close(); 12 } 13 }
其返回结果:
1IndexResponse[index=ubi_201904,type=_doc,id=lCJZ-GkBrOLJP-QWff3I,version=1,result=created,seqNo=0,primaryTerm=1,shards={"total":2,"successful":1,"failed":0}]
那如果能匹配到多个模板呢?
多个索引模板可能匹配一个索引,可以使用order属性为索引模板指定顺序。从顺序较小的开始寻找,order越大,越优先(前提是匹配模板表达式)。
举例如下:
1PUT /_template/template_1 2{ 3 "index_patterns" : ["*"], 4 "order" : 0, 5 "settings" : { 6 "number_of_shards" : 1 7 }, 8 "mappings" : { 9 "_doc" : { 10 "_source" : { "enabled" : false } 11 } 12 } 13} 14 15PUT /_template/template_2 16{ 17 "index_patterns" : ["te*"], 18 "order" : 1, 19 "settings" : { 20 "number_of_shards" : 1 21 }, 22 "mappings" : { 23 "_doc" : { 24 "_source" : { "enabled" : true } 25 } 26 } 27}
首先从order=0进行匹配,由于其表达式为*,则默认会全匹配,故首先尝试使用该模板,然后再遍历下一个模板,也就是order=1的模板,如果匹配,则使用第二个模板的配置,如果不匹配,则使用第一个模板的配置,依次类推。
其匹配的具体实现逻辑大概如下:
1、对所有的模板按照order属性进行升序排序。
2、遍历所有的模板,进行表达式匹配,匹配成功,则设置为当前匹配模板,然后判断下一个,直到把所有的模板都处理过。
3、选最后匹配的模板当成最后的模板。
那如果存在多个模板,其order相同,那其顺序能保证吗?
答案是不能保证,因为对所有模板进行排序的过程中,如果order相同,其顺序无法得到保证。
思考:索引模板的使用场景是什么呢?欢迎大家留言讨论。