Учебник: Преобразование образцовых данных электронной коммерции
Преобразования позволяют извлекать информацию из индекса Elasticsearch, преобразовывать её и сохранять в другом индексе. Давайте воспользуемся данными примера из Kibana, чтобы продемонстрировать, как можно сворачивать и обобщать данные с помощью преобразований.
- Убедитесь, что ваша среда настроена должным образом для использования преобразований. Если включены функции безопасности Elasticsearch, для выполнения этого урока вам нужен пользователь с правами на просмотр и создание преобразований. Вам также необходимы определённые права на индексы источника и назначения. См. Настройка.
-
Выберите свой исходный индекс.
В этом примере мы будем использовать примерные данные о заказах электронной коммерции. Если вы ещё не знакомы с индексом
kibana_sample_data_ecommerce, используйте панель Доходы в Kibana для изучения данных. Подумайте, какие выводы вы хотели бы получить из этих данных электронной коммерции. -
Выберите тип преобразования сворачивания и поэкспериментируйте с различными вариантами группирования и агрегирования данных.
Существует два типа преобразований, но сначала мы попробуем свернуть ваши данные, что предполагает использование по крайней мере одного поля для группировки и применения по крайней мере одной агрегации. Вы можете предварительно просмотреть, как будут выглядеть преобразованные данные, поэтому не стесняйтесь поиграться! Вы также можете включить гистограммы, чтобы лучше понять распределение значений в ваших данных.
Например, вы можете сгруппировать данные по идентификатору продукта и рассчитать общее количество продаж для каждого продукта и его среднюю цену. Или вы можете изучить поведение отдельных клиентов и рассчитать, сколько каждый клиент потратил в общей сложности и сколько различных категорий продуктов они приобрели. Или вы можете учесть валюты или географические данные. Какие наиболее интересные способы преобразования и интерпретации этих данных?
Перейдите в Управление > Управление стеком > Данные > Преобразования в Kibana и используйте мастера для создания преобразования:
Сгруппируйте данные по идентификатору клиента и добавьте одну или несколько агрегаций, чтобы узнать больше о заказах каждого клиента. Например, давайте вычислим сумму приобретённых ими продуктов, общую стоимость их покупок, максимальное количество продуктов, приобретённых в одном заказе, и общее количество их заказов. Мы добьёмся этого, используя
sumагрегацию по полямtotal_quantityиtaxless_total_price,maxагрегацию по полюtotal_quantityиcardinalityагрегацию по полюorder_id:Если вас интересует подмножество данных, вы можете необязательно включить элемент запроса. В этом примере мы отфильтровали данные, чтобы рассматривать только заказы с
currencyзначениемEUR. В качестве альтернативы, мы также могли сгруппировать данные по этому полю. Если вы хотите использовать более сложные запросы, вы можете создать свою таблицу данных из сохранённого запроса.Если хотите, можете использовать API-превью преобразований.
Пример API
resp = client.transform.preview_transform( source={ "index": "kibana_sample_data_ecommerce", "query": { "bool": { "filter": { "term": { "currency": "EUR" } } } } }, pivot={ "group_by": { "customer_id": { "terms": { "field": "customer_id" } } }, "aggregations": { "total_quantity.sum": { "sum": { "field": "total_quantity" } }, "taxless_total_price.sum": { "sum": { "field": "taxless_total_price" } }, "total_quantity.max": { "max": { "field": "total_quantity" } }, "order_id.cardinality": { "cardinality": { "field": "order_id" } } } }, ) print(resp)const response = await client.transform.previewTransform({ source: { index: "kibana_sample_data_ecommerce", query: { bool: { filter: { term: { currency: "EUR", }, }, }, }, }, pivot: { group_by: { customer_id: { terms: { field: "customer_id", }, }, }, aggregations: { "total_quantity.sum": { sum: { field: "total_quantity", }, }, "taxless_total_price.sum": { sum: { field: "taxless_total_price", }, }, "total_quantity.max": { max: { field: "total_quantity", }, }, "order_id.cardinality": { cardinality: { field: "order_id", }, }, }, }, }); console.log(response);POST _transform/_preview { "source": { "index": "kibana_sample_data_ecommerce", "query": { "bool": { "filter": { "term": {"currency": "EUR"} } } } }, "pivot": { "group_by": { "customer_id": { "terms": { "field": "customer_id" } } }, "aggregations": { "total_quantity.sum": { "sum": { "field": "total_quantity" } }, "taxless_total_price.sum": { "sum": { "field": "taxless_total_price" } }, "total_quantity.max": { "max": { "field": "total_quantity" } }, "order_id.cardinality": { "cardinality": { "field": "order_id" } } } } } -
Когда вы будете удовлетворены тем, что видите в предварительном просмотре, создайте преобразование.
- Укажите идентификатор преобразования, имя индекса назначения и, необязательно, описание. Если индекс назначения не существует, он будет автоматически создан при запуске преобразования.
- Решите, хотите ли вы, чтобы преобразование выполнялось один раз или непрерывно. Поскольку этот индекс с данными примера не меняется, давайте воспользуемся стандартным поведением и выполним преобразование один раз. Однако, если вы хотите попробовать, нажмите Непрерывный режим. Вы должны выбрать поле, которое преобразование может использовать для проверки, какие сущности изменились. Как правило, рекомендуется использовать поле отметки времени загрузки. Однако в данном примере вы можете использовать поле
order_date. - Необязательно, вы можете настроить политику хранения, которая применяется к вашему преобразованию. Выберите поле даты, используемое для определения старых документов в целевом индексе, и укажите максимальный срок действия. Документы, которые старше заданного значения, удаляются из целевого индекса.
В Kibana, прежде чем завершить создание преобразования, вы можете скопировать запрос API преобразования предварительного просмотра в буфер обмена. Эта информация полезна позднее, когда вы решаете, хотите ли вы вручную создать целевой индекс.
Если предпочитаете, можете воспользоваться API создания преобразований.
Пример API
resp = client.transform.put_transform( transform_id="ecommerce-customer-transform", source={ "index": [ "kibana_sample_data_ecommerce" ], "query": { "bool": { "filter": { "term": { "currency": "EUR" } } } } }, pivot={ "group_by": { "customer_id": { "terms": { "field": "customer_id" } } }, "aggregations": { "total_quantity.sum": { "sum": { "field": "total_quantity" } }, "taxless_total_price.sum": { "sum": { "field": "taxless_total_price" } }, "total_quantity.max": { "max": { "field": "total_quantity" } }, "order_id.cardinality": { "cardinality": { "field": "order_id" } } } }, dest={ "index": "ecommerce-customers" }, retention_policy={ "time": { "field": "order_date", "max_age": "60d" } }, ) print(resp)const response = await client.transform.putTransform({ transform_id: "ecommerce-customer-transform", source: { index: ["kibana_sample_data_ecommerce"], query: { bool: { filter: { term: { currency: "EUR", }, }, }, }, }, pivot: { group_by: { customer_id: { terms: { field: "customer_id", }, }, }, aggregations: { "total_quantity.sum": { sum: { field: "total_quantity", }, }, "taxless_total_price.sum": { sum: { field: "taxless_total_price", }, }, "total_quantity.max": { max: { field: "total_quantity", }, }, "order_id.cardinality": { cardinality: { field: "order_id", }, }, }, }, dest: { index: "ecommerce-customers", }, retention_policy: { time: { field: "order_date", max_age: "60d", }, }, }); console.log(response);PUT _transform/ecommerce-customer-transform { "source": { "index": [ "kibana_sample_data_ecommerce" ], "query": { "bool": { "filter": { "term": { "currency": "EUR" } } } } }, "pivot": { "group_by": { "customer_id": { "terms": { "field": "customer_id" } } }, "aggregations": { "total_quantity.sum": { "sum": { "field": "total_quantity" } }, "taxless_total_price.sum": { "sum": { "field": "taxless_total_price" } }, "total_quantity.max": { "max": { "field": "total_quantity" } }, "order_id.cardinality": { "cardinality": { "field": "order_id" } } } }, "dest": { "index": "ecommerce-customers" }, "retention_policy": { "time": { "field": "order_date", "max_age": "60d" } } } -
Необязательно: создайте целевой индекс.
Если целевой индекс не существует, он создаётся при первом запуске преобразования. Преобразование сворачивания определяет соответствия для целевого индекса на основе исходных индексов и агрегаций преобразования. Если в целевом индексе есть поля, полученные из скриптов (например, если вы используете
scripted_metricsилиbucket_scriptsагрегации), они создаются с динамическими соответствиями. Вы можете использовать API-превью преобразований для предварительного просмотра соответствий, которые он будет использовать для целевого индекса. В Kibana, если вы скопировали запрос API в буфер обмена, вставьте его в консоль, затем обратитесь к объектуgenerated_dest_indexв ответе API.Преобразования могут иметь больше вариантов конфигурации, предоставляемых API, чем доступные варианты в Kibana. Например, вы можете установить конвейер загрузки для
dest, вызвав создание преобразования. Для всех вариантов конфигурации преобразования обратитесь к документации.Пример API
{ "preview" : [ { "total_quantity" : { "max" : 2, "sum" : 118.0 }, "taxless_total_price" : { "sum" : 3946.9765625 }, "customer_id" : "10", "order_id" : { "cardinality" : 59 } }, ... ], "generated_dest_index" : { "mappings" : { "_meta" : { "_transform" : { "transform" : "transform-preview", "version" : { "created" : "8.0.0" }, "creation_date_in_millis" : 1621991264061 }, "created_by" : "transform" }, "properties" : { "total_quantity.sum" : { "type" : "double" }, "total_quantity" : { "type" : "object" }, "taxless_total_price" : { "type" : "object" }, "taxless_total_price.sum" : { "type" : "double" }, "order_id.cardinality" : { "type" : "long" }, "customer_id" : { "type" : "keyword" }, "total_quantity.max" : { "type" : "integer" }, "order_id" : { "type" : "object" } } }, "settings" : { "index" : { "number_of_shards" : "1", "auto_expand_replicas" : "0-1" } }, "aliases" : { } } }В некоторых случаях выведенные соответствия могут быть несовместимы с фактическими данными. Например, могут произойти переполнения чисел или динамически сопоставленные поля могут содержать как числа, так и строки. Чтобы избежать этой проблемы, создайте целевой индекс перед запуском преобразования. Дополнительная информация приведена в документации API создания индекса.
Пример API
Вы можете использовать информацию из предварительного просмотра преобразования для создания целевого индекса. Например:
resp = client.indices.create( index="ecommerce-customers", mappings={ "properties": { "total_quantity.sum": { "type": "double" }, "total_quantity": { "type": "object" }, "taxless_total_price": { "type": "object" }, "taxless_total_price.sum": { "type": "double" }, "order_id.cardinality": { "type": "long" }, "customer_id": { "type": "keyword" }, "total_quantity.max": { "type": "integer" }, "order_id": { "type": "object" } } }, ) print(resp)response = client.indices.create( index: 'ecommerce-customers', body: { mappings: { properties: { 'total_quantity.sum' => { type: 'double' }, total_quantity: { type: 'object' }, taxless_total_price: { type: 'object' }, 'taxless_total_price.sum' => { type: 'double' }, 'order_id.cardinality' => { type: 'long' }, customer_id: { type: 'keyword' }, 'total_quantity.max' => { type: 'integer' }, order_id: { type: 'object' } } } } ) puts responseconst response = await client.indices.create({ index: "ecommerce-customers", mappings: { properties: { "total_quantity.sum": { type: "double", }, total_quantity: { type: "object", }, taxless_total_price: { type: "object", }, "taxless_total_price.sum": { type: "double", }, "order_id.cardinality": { type: "long", }, customer_id: { type: "keyword", }, "total_quantity.max": { type: "integer", }, order_id: { type: "object", }, }, }, }); console.log(response);PUT /ecommerce-customers { "mappings": { "properties": { "total_quantity.sum" : { "type" : "double" }, "total_quantity" : { "type" : "object" }, "taxless_total_price" : { "type" : "object" }, "taxless_total_price.sum" : { "type" : "double" }, "order_id.cardinality" : { "type" : "long" }, "customer_id" : { "type" : "keyword" }, "total_quantity.max" : { "type" : "integer" }, "order_id" : { "type" : "object" } } } } -
Запустите преобразование.
Несмотря на то, что использование ресурсов автоматически корректируется в зависимости от нагрузки кластера, преобразование увеличивает нагрузку на поиск и индексирование в кластере во время его выполнения. Однако, если вы столкнётесь с чрезмерной нагрузкой, вы можете остановить его.
Вы можете запускать, останавливать, сбрасывать и управлять преобразованиями в Kibana:
В качестве альтернативы вы можете воспользоваться API запуска преобразований, API остановки преобразований и API сброса преобразований.
Если вы сбросите преобразование, все контрольные точки, состояния и целевой индекс (если он был создан преобразованием) будут удалены. Преобразование готово к запуску снова, как если бы оно только что было создано.
Пример API
resp = client.transform.start_transform( transform_id="ecommerce-customer-transform", ) print(resp)response = client.transform.start_transform( transform_id: 'ecommerce-customer-transform' ) puts response
const response = await client.transform.startTransform({ transform_id: "ecommerce-customer-transform", }); console.log(response);POST _transform/ecommerce-customer-transform/_start
Если вы выбрали пакетное преобразование, это единственное действие с единственной контрольной точкой. Вы не можете перезапустить его после завершения. Преобразования в непрерывном режиме отличаются тем, что они постоянно увеличивают и обрабатывают контрольные точки по мере добавления новых исходных данных.
-
Изучите данные в вашем новом индексе.
Например, используйте приложение Обзор в Kibana:
-
Необязательно: Создайте другой трансформирование, на этот раз используя метод
latest.Этот метод заполняет индекс назначения последними документами для каждого уникального значения ключа. Например, вы можете найти последние заказы (отсортированные по полю
order_date) для каждого клиента или для каждой страны и региона.Пример API
resp = client.transform.preview_transform( source={ "index": "kibana_sample_data_ecommerce", "query": { "bool": { "filter": { "term": { "currency": "EUR" } } } } }, latest={ "unique_key": [ "geoip.country_iso_code", "geoip.region_name" ], "sort": "order_date" }, ) print(resp)const response = await client.transform.previewTransform({ source: { index: "kibana_sample_data_ecommerce", query: { bool: { filter: { term: { currency: "EUR", }, }, }, }, }, latest: { unique_key: ["geoip.country_iso_code", "geoip.region_name"], sort: "order_date", }, }); console.log(response);POST _transform/_preview { "source": { "index": "kibana_sample_data_ecommerce", "query": { "bool": { "filter": { "term": {"currency": "EUR"} } } } }, "latest": { "unique_key": ["geoip.country_iso_code", "geoip.region_name"], "sort": "order_date" } }Если индекс назначения не существует, он создается при первом запуске трансформации. Однако, в отличие от трансформаций типа pivot, трансформации типа latest не вычисляют определения сопоставления при создании индекса. Вместо этого они используют динамические сопоставления. Для использования явных сопоставлений создайте индекс назначения перед запуском трансформации.
- Если вы не хотите сохранять трансформирование, вы можете удалить его в Kibana или использовать API удаления трансформирования. По умолчанию, при удалении трансформирования его индекс назначения и шаблоны индексов Kibana остаются.
Теперь, когда вы создали простые трансформирования для выборочных данных Kibana, рассмотрите возможные варианты использования для ваших собственных данных. Для получения дополнительных идей ознакомьтесь со статьей Когда использовать трансформирования и примерами.
© 2023-2025 Elasticsearch
As of September 2024, Elasticsearch is available under a choice of three licenses: the Server Side Public License (SSPL), the Elastic License, or the AGPLv3 (OSI approved).
Elasticsearch and the Elasticsearch logo are trademarks of Elasticsearch B.V., registered in the U.S. and in other countries.
https://www.elastic.co/guide/en/elasticsearch/reference/8.17/ecommerce-transforms.html