Elasticsearch Index template

2021-09-16 10:04:44 浏览数 (1)

简介

Index template定义在创建新index时可以自动应用的 settings 和 mappings。 Elasticsearch 根据与 index 名称匹配的 index 模式将模板应用于新索引。这个对于我们想创建的一系列的 Index 具有同样的 settings 及 mappings。比如我们希望每一天/月的日志的index都具有同样的设置。

Index template 仅在 index 创建期间应用。 对 index template 的更改不会影响现有索引。 create index API 请求中指定的设置和映射会覆盖索引模板中指定的任何设置或映射。

Index template

我们可以使用如下的接口来定义一个 index template:

代码语言:javascript复制
PUT /_template/<index-template>

我们可以使用_template这个终点来创建,删除,查看一个 index template。下面,我们来举一个例子:

代码语言:javascript复制
PUT _template/logs_template
{
  "index_patterns": "logs-*",
  "order": 1,
  "settings": {
    "number_of_shards": 4,
    "number_of_replicas": 1
  },
  "mappings": {
    "properties": {
      "@timestamp": {
        "type": "date"
      }
    }
  }
}

#索引模板
PUT _template/index_template
{
  "index_patterns": "*", // 匹配任何模板
  "order": 1, // 模板的权重, 多个模板的时候优先匹配用, 值越大, 权重越高
  "settings": {
    "number_of_shards": 1,
    "number_of_replicas": 0
  },
  "mappings": {
    "properties": {
      "utime": {
        "type": "date",
        "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
      },
      "ctime": {
        "type": "date",
        "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
      },
      "indextype": {
        "type": "keyword"
      },
      "@version": {
         "doc_values": true,
         "index": "false",   // 设置为false 不索引。Es6之前版本"index": "not_analyzed"
         "type": "text"
      }
    }
  },
  "aliases": {
    "{index}-alias": {}  // 索引对应的别名
  }
}

1. 直接修改mapping的优先级 > 索引模板中的设置;
2. 索引匹配了多个template, 当属性等配置出现不一致时, 以模板的权重(order属性的值)为准, 值越大越优先, order的默认值是0
3. ES 6.0之后的版本API变化较大, 请重点关注.

在上面,我们可以看到,我们定义了一个叫做 logs_template 的 index template。它的 index_patterns 定义为 “logs-*”,说明,任何以 “logs-” 为开头的任何一个 index 将具有在该 template 里具有的 settings 及 mappings 属性。这里的 “order” 的意思是:如果索引与多个模板匹配,则 Elasticsearch 应用此模板的顺序。该值为1,表明有最先合并,如果有更高 order 的 template,这个 settings 或 mappings 有可能被其它的 template 所覆盖。

下面,我们来测试一下我们刚定义的index template:

代码语言:javascript复制
PUT logs-2019-03-01

在这里,我们创建了一个叫做 logs-2019-03-01 的 index。我们使用如下的命令来检查被创建的情况:

代码语言:javascript复制
GET logs-2019-03-01

显示的结果为:

代码语言:javascript复制
{
  "logs-2019-03-01" : {
    "aliases" : { },
    "mappings" : {
      "_doc" : {
        "properties" : {
          "@timestamp" : {
            "type" : "date"
          }
        }
      }
    },
    "settings" : {
      "index" : {
        "creation_date" : "1610522597177",
        "number_of_shards" : "4",
        "number_of_replicas" : "1",
        "uuid" : "hmQoCc9vRkWtSbOY8arxBA",
        "version" : {
          "created" : "6070299"
        },
        "provided_name" : "logs-2019-03-01"
      }
    }
  }
}

我们已经成功创建了一个我们想要的 index,并且它具有我们之前定义的 settings 及 mappings。

设置alias

我们甚至可以为我们的 index template 添加 index alias:

代码语言:javascript复制
PUT _template/logs_template
{
  "index_patterns": "logs-*",
  "order": 1,
  "settings": {
    "number_of_shards": 4,
    "number_of_replicas": 1
  },
  "mappings": {
    "properties": {
      "@timestamp": {
        "type": "date"
      }
    }
  },
  "aliases": {
    "{index}-alias": {}  // 索引对应的别名
  }
}

在上面,我们已经创立了一个叫做 {index}-alias 的别名。这里的 {index} 就是实际生成 index 的文件名来代替。我们下面用一个例子来说明:

代码语言:javascript复制
PUT logs-2019-04-01

我们创建一个叫做 logs-2019-04-01 的index, 那么它同时生成了一个叫做 logs-2019-04-01-alias 的别名。我们可以通过如下的命令来检查:

代码语言:javascript复制
GET logs-2019-04-01-alias

Index 匹配多template

多个索引模板可能与索引匹配,在这种情况下,设置和映射都合并到索引的最终配置中。 可以使用 order 参数控制合并的顺序,首先应用较低的顺序,并且覆盖它们的较高顺序。 例如:

代码语言:javascript复制
PUT /_template/template_1
{
  "index_patterns": ["*"],
  "order": 0,
  "settings": {
    "number_of_shards": 1
  },
  "mappings": {
    "_source": {
      "enabled": false
    }
  }
} 

PUT /_template/template_2
{
  "index_patterns": ["te*"],
  "order": 1,
  "settings": {
    "number_of_shards": 1
  },
  "mappings": {
    "_source": {
      "enabled": true
    }
  }
}

以上的 template_1 将禁用存储 _source,但对于以 te* 开头的索引,仍将启用 _source。 注意,对于映射,合并是 “深度” 的,这意味着可以在高阶模板上轻松添加覆盖特定的基于对象属性的映射,而较低阶模板提供基础。

我们可以来创建一个例子看看:

代码语言:javascript复制
PUT test10 

GET test10

结果:
{
    "test10":{
        "aliases":{

        },
        "mappings":{

        },
        "settings":{
            "index":{
                "creation_date":"1567654333181",
                "number_of_shards":"1",
                "number_of_replicas":"1",
                "uuid":"iEwaQFl9RAKyTt79PduN-Q",
                "version":{
                    "created":"7030099"
                },
                "provided_name":"test10"
            }
        }
    }
}

如果我们创建另外一个不是以  “te” 开头的 index,我们可以看看如下的情况:

代码语言:javascript复制
PUT my_test_index

GET my_test_index

结果:
{
    "my_test_index":{
        "aliases":{

        },
        "mappings":{
            "_source":{
                "enabled":false
            }
        },
        "settings":{
            "index":{
                "creation_date":"1567654713059",
                "number_of_shards":"1",
                "number_of_replicas":"1",
                "uuid":"aSsIZMT2RyWKT44G2dF2zg",
                "version":{
                    "created":"7030099"
                },
                "provided_name":"my_test_index"
            }
        }
    }
}

显然在 mappings 里显示 source 是被禁止的。

如果对于两个templates来说,如果 order 是一样的话,我们可能陷于一种不可知论的合并状态。在实际的使用中必须避免。

查询 Index template

我们可以通过如下的接口来查询已经被创建好的 index template:

代码语言:javascript复制
GET /_template/<index-template>

比如:
GET _template/logs_template

显示的内容就是我们之前已经创建的那个 index template。你也可以通过如下的方式来同时查询多个 template 的情况:

代码语言:javascript复制
GET _template                // 查看所有模板
GET _template/temp*          // 查看与通配符相匹配的模板
GET _template/temp1,temp2    // 查看多个模板
GET _template/shop_template  // 查看指定模板

判断模板是否存在:

代码语言:javascript复制
HEAD _template/shop_tem

结果说明:
如果存在, 响应结果是: 200 - OK
如果不存在, 响应结果是: 404 - Not Found

删除 Index template

在之前的练习中,我们匹配 “*”,也就是我们以后所有的创建的新的 index 将不存储 source,这个显然不是我们所需要的。我们需要来把这个 template 进行删除。删除一个 template 的接口如下:

代码语言:javascript复制
DELETE /_template/<index-template>

那么针对我们的情况,我们可以使用如下的命令来删除我们不需要的 template:

代码语言:javascript复制
DELETE _template/template_1  // 删除上述创建的模板
DELETE _template/template_2

这样我们删除了我们刚才创建的两个 templates。

模板的使用建议

如果我们只关心查询的评分结果, 而不用查看原始文档的内容, 就设置"_source": {"enabled": false}。这能节省磁盘空间并减少磁盘IO上的开销。

如果能够确切地知道要对哪个field做查询操作, 就设置"_all": {"enabled": false}。这能实现性能提升, 并节省存储空间。而在6.X版本开始,_all字段也不再支持了, ES官方建议我们通过copy_to自定义我们自己的all字段。

如果我们的数据是结构化数据, 就设置"dynamic": "strict"。把动态类型判断设置为严格, 也就是不允许ES为插入的数据进行动态类型设置, 避免注入脏数据。

如果我们只关心精确匹配, 就设置test_field: {"type": "keyword"}。keyword类型要比text类型的性能更高, 并且还能节省磁盘的存储空间。

参考

【1】https://www.elastic.co/guide/en/elasticsearch/reference/7.4/indices-get-template.html

【2】https://www.elastic.co/guide/en/elasticsearch/reference/7.4/indices-delete-template.html

【3】https://www.elastic.co/guide/en/elasticsearch/reference/7.4/indices-templates.html

0 人点赞