Шаблоны индексов Elasticsearch позволяют определить шаблоны, которые будут автоматически применяться при создании индекса. Шаблоны могут включать как настройки, так и маппинги.
Что мы делаем?
Мы хотим создать шаблон того, как должен выглядеть целевой индекс. Он должен состоять из 1 основного и 2 копийных шардов, и мы хотим обновить маппинг, чтобы можно было использовать текстовые поля и поля строк ключевых слов.
Таким образом, всякий раз, когда мы создаем индекс, соответствующий нашему шаблону, этот шаблон будет применяться при создании индекса.
Строковые поля
В наших маппингах мы будем использовать следующие строковые поля, которые будут включены в наши шаблоны:
Text
Поле для индексации полнотекстовых значений, таких как тело письма или описание товара. Перед индексацией эти поля анализируются, т.е. проходят через анализатор, преобразующий строку в список отдельных терминов. Процесс анализа позволяет Elasticsearch осуществлять поиск отдельных слов в каждом полнотекстовом поле
Keyword
Поле для индексирования структурированного содержимого, такого как адреса электронной почты, имена хостов, коды статуса, почтовые индексы или теги.
Они обычно используются для фильтрации, для сортировки и для агрегирования. Поиск по ключевым словам возможен только по их точному значению.
Замечание по поводу шаблонов:
Следует иметь в виду несколько моментов:
- Шаблоны ссылаются при создании индекса и не влияют на существующие индексы
- При обновлении шаблона необходимо указывать точный шаблон, полезная нагрузка перезаписывает весь шаблон
Просмотр текущих шаблонов в кластере:
1 2 3 4 | curl -XGET http://localhost:9200/_cat/templates?v name index_patterns order version .monitoring-kibana [.monitoring-kibana-6-*] 0 6020099 filebeat-6.3.1 [filebeat-6.3.1-*] 1 |
Создайте шаблон foobar_docs, который будет соответствовать всем индексам, соответствующим foo-* и bar-*, которые унаследуют настройки индексов 1 основного шарда и 2 реплицированных шардов, а также примените шаблон маппинга, показанный ниже:
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 | curl -H 'Content-Type: application/json' -XPUT http://localhost:9200/_template/foobar_docs -d ' { "index_patterns": [ "foo-*", "bar-*" ], "settings": { "number_of_shards": 1, "number_of_replicas": 2 }, "mappings": { "type1": { "_source": {"enabled": true}, "properties": {"created_at": {"type": "date"}, "title": {"type": "text"}, "status": {"type": "keyword"}, "content": {"type":"text"}, "first_name": {"type": "keyword"}, "last_name": {"type": "keyword"}, "age": {"type":"integer"}, "registered": {"type": "boolean"} } } } }' {"acknowledged":true} |
Просмотр шаблона из api:
1 2 3 | curl -XGET http://localhost:9200/_cat/templates/foobar_docs?v name index_patterns order version foobar_docs [foo-*, bar-*] 0 |
Создайте индекс, который будет соответствовать определению шаблонов:
1 2 | curl -H 'Content-Type: application/json' -XPUT http://localhost:9200/test-2023.07.20 {"acknowledged":true,"shards_acknowledged":true,"index":"test-2023.07.20"} |
Убедитесь, что индекс создан:
1 2 3 | curl -XGET http://localhost:9200/_cat/indices/test-2023.07.20?v health status index uuid pri rep docs.count docs.deleted store.size pri.store.size green open test-2023.07.20 -5XOfl0GTEGeHycTwL51vQ 5 1 0 0 2kb 1.1kb |
Мы также можем проинспектировать шаблон, как показано ниже:
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 50 | curl -XGET http://localhost:9200/_template/foobar_docs?pretty { "foobar_docs" : { "order" : 0, "index_patterns" : [ "foo-*", "bar-*" ], "settings" : { "index" : { "number_of_shards" : "1", "number_of_replicas" : "2" } }, "mappings" : { "type1" : { "_source" : { "enabled" : true }, "properties" : { "created_at" : { "type" : "date" }, "title" : { "type" : "text" }, "status" : { "type" : "keyword" }, "content" : { "type" : "text" }, "first_name" : { "type" : "keyword" }, "last_name" : { "type" : "keyword" }, "age" : { "type" : "integer" }, "registered" : { "type" : "boolean" } } } }, "aliases" : { } } } |
Добавьте документ в индекс:
1 2 3 4 5 6 7 8 9 10 | curl -H 'Content-Type: application/json' -XPOST http://localhost:9200/foo-2023.07.20/type1/ -d ' { "title": "this is a post", "status": "active", "content": "introduction post", "first_name": "ruan", "last_name": "bekker", "age": "31", "registered": "true" }' |
Запустите поиск по индексу elasticsearch для просмотра данных:
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 | curl -XGET http://localhost:9200/foo-2023.07.20/_search?pretty { "took" : 1, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : 1, "max_score" : 1.0, "hits" : [ { "_index" : "foo-2023.07.20", "_type" : "type1", "_id" : "ZYfotmQB9mQGWzJT7W2y", "_score" : 1.0, "_source" : { "title" : "this is a post", "status" : "active", "content" : "introduction post", "first_name" : "ruan", "last_name" : "bekker", "age" : "31", "registered" : "true" } } ] } } |
Создайте другой документ:
1 2 3 4 5 6 7 8 9 10 11 | curl -H 'Content-Type: application/json' -XPOST http://localhost:9200/foo-2023.07.20/type1/ -d ' { "created_at": 1532077144, "title": "this is a another post", "status": "ae", "content": "introduction post", "first_name": "stefan", "last_name": "bester", "age": 34, "registered": "true" }' |
Как вы уже догадались, выполнение другого поиска в elasticsearch показывает нам оба документа:
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 | curl -XGET http://localhost:9200/foo-2023.07.20/_search?pretty { "took" : 0, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : 2, "max_score" : 1.0, "hits" : [ { "_index" : "foo-2023.07.20", "_type" : "type1", "_id" : "ZYfotmQB9mQGWzJT7W2y", "_score" : 1.0, "_source" : { "title" : "this is a post", "status" : "active", "content" : "introduction post", "first_name" : "ruan", "last_name" : "bekker", "age" : "31", "registered" : "true" } }, { "_index" : "foo-2023.07.20", "_type" : "type1", "_id" : "rofrtmQB9mQGWzJTxnvp", "_score" : 1.0, "_source" : { "created_at" : 1532077144, "title" : "this is a another post", "status" : "active", "content" : "introduction post", "first_name" : "stefan", "last_name" : "bester", "age" : 34, "registered" : "true" } } ] } } |
Запустим поисковый запрос на поиск любых документов, в которых встречаются люди с возрастом от 30 до 40 лет:
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 | curl -H 'Content-Type: application/json' -XGET http://localhost:9200/foo-2023.07.20/_search?pretty -d '{"query": {"range": {"age": {"gte": 30, "lte": 40}}}}' { "took" : 2, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : 2, "max_score" : 1.0, "hits" : [ { "_index" : "foo-2023.07.20", "_type" : "type1", "_id" : "ZYfotmQB9mQGWzJT7W2y", "_score" : 1.0, "_source" : { "title" : "this is a post", "status" : "active", "content" : "introduction post", "first_name" : "ruan", "last_name" : "bekker", "age" : "31", "registered" : "true" } }, { "_index" : "foo-2023.07.20", "_type" : "type1", "_id" : "rofrtmQB9mQGWzJTxnvp", "_score" : 1.0, "_source" : { "created_at" : 1532077144, "title" : "this is a another post", "status" : "active", "content" : "introduction post", "first_name" : "stefan", "last_name" : "bester", "age" : 34, "registered" : "true" } } ] } } |
Поиск людей с возрастом от 32 до 40 лет:
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 | curl -H 'Content-Type: application/json' -XGET http://localhost:9200/foo-2023.07.20/_search?pretty -d '{"query": {"range": {"age": {"gte": 32, "lte": 40}}}}' { "took" : 1, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : 1, "max_score" : 1.0, "hits" : [ { "_index" : "foo-2023.07.20", "_type" : "type1", "_id" : "rofrtmQB9mQGWzJTxnvp", "_score" : 1.0, "_source" : { "created_at" : 1532077144, "title" : "this is a another post", "status" : "active", "content" : "introduction post", "first_name" : "stefan", "last_name" : "bester", "age" : 34, "registered" : "true" } } ] } } |
Допустим, мы хотим обновить наш шаблон с настройками refresh_interval, primary шардов - 2, реплик - 1:
1 2 3 4 5 | curl -H 'Content-Type: application/json' -XPUT http://localhost:9200/_template/foobar_docs -d ' { "index_patterns": ["foo-*", "bar-*"], "settings": {"number_of_shards": 2, "number_of_replicas": 1, "refresh_interval": "15s"} }' |
Просмотрите шаблон, как видите, целевой шаблон будет выглядеть точно так же, как тело данных, которое мы размещаем в шаблоне api:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | curl -XGET http://localhost:9200/_template/foobar_docs?pretty { "foobar_docs" : { "order" : 0, "index_patterns" : [ "foo-*", "bar-*" ], "settings" : { "index" : { "number_of_shards" : "2", "number_of_replicas" : "1", "refresh_interval" : "15s" } }, "mappings" : { }, "aliases" : { } } } |
Просмотрите наш текущий индекс, как вы видите, индекс не затронут изменением шаблона, так как только новые индексы получат обновление шаблона:
1 2 3 | curl -XGET http://localhost:9200/_cat/indices/foo-2023.07.20?v health status index uuid pri rep docs.count docs.deleted store.size pri.store.size yellow open foo-2023.07.20 ol1pGugrQCKd0xES4R6oFg 1 2 2 0 20.4kb 10.2kb |
Создайте новый индекс и убедитесь, что конфигурация шаблона подтягивается в новый индекс:
1 | curl -H 'Content-Type: application/json' -XPUT http://localhost:9200/foo-2023.07.20-new |
Просмотрите индексы elasticsearch, чтобы проверить их поведение:
1 2 3 4 | curl -XGET http://localhost:9200/_cat/indices/foo-2023.07.*?v health status index uuid pri rep docs.count docs.deleted store.size pri.store.size yellow open foo-2023.07.20 ol1pGugrQCKd0xES4R6oFg 1 2 2 0 20.4kb 10.2kb green open foo-2023.07.20-new g6Ii8jtKRFa1zDVB2IsDBQ 2 1 0 0 920b 460b |
Удалите индексы:
1 2 | curl -XDELETE http://localhost:9200/foo-* {"acknowledged":true} |
Удалить шаблоны:
1 2 | curl -XDELETE 'http://localhost:9200/_template/foobar_docs' {"acknowledged":true} |
Убедитесь, что шаблоны исчезли:
1 2 | curl -XGET http://localhost:9200/_cat/templates/foobar_docs?v name index_patterns order version |