Spec-Zone.ru › Elasticsearch 8
›Elasticsearch Guide [8.17] ›Свертка или преобразование данных ›Преобразование данных

Учебник: Преобразование образцовых данных электронной коммерции

Преобразования позволяют извлекать информацию из индекса Elasticsearch, преобразовывать её и сохранять в другом индексе. Давайте воспользуемся данными примера из Kibana, чтобы продемонстрировать, как можно сворачивать и обобщать данные с помощью преобразований.

  1. Убедитесь, что ваша среда настроена должным образом для использования преобразований. Если включены функции безопасности Elasticsearch, для выполнения этого урока вам нужен пользователь с правами на просмотр и создание преобразований. Вам также необходимы определённые права на индексы источника и назначения. См. Настройка.
  2. Выберите свой исходный индекс.

    В этом примере мы будем использовать примерные данные о заказах электронной коммерции. Если вы ещё не знакомы с индексом kibana_sample_data_ecommerce, используйте панель Доходы в Kibana для изучения данных. Подумайте, какие выводы вы хотели бы получить из этих данных электронной коммерции.

  3. Выберите тип преобразования сворачивания и поэкспериментируйте с различными вариантами группирования и агрегирования данных.

    Существует два типа преобразований, но сначала мы попробуем свернуть ваши данные, что предполагает использование по крайней мере одного поля для группировки и применения по крайней мере одной агрегации. Вы можете предварительно просмотреть, как будут выглядеть преобразованные данные, поэтому не стесняйтесь поиграться! Вы также можете включить гистограммы, чтобы лучше понять распределение значений в ваших данных.

    Например, вы можете сгруппировать данные по идентификатору продукта и рассчитать общее количество продаж для каждого продукта и его среднюю цену. Или вы можете изучить поведение отдельных клиентов и рассчитать, сколько каждый клиент потратил в общей сложности и сколько различных категорий продуктов они приобрели. Или вы можете учесть валюты или географические данные. Какие наиболее интересные способы преобразования и интерпретации этих данных?

    Перейдите в Управление > Управление стеком > Данные > Преобразования в Kibana и используйте мастера для создания преобразования:

    Creating a simple transform in Kibana

    Сгруппируйте данные по идентификатору клиента и добавьте одну или несколько агрегаций, чтобы узнать больше о заказах каждого клиента. Например, давайте вычислим сумму приобретённых ими продуктов, общую стоимость их покупок, максимальное количество продуктов, приобретённых в одном заказе, и общее количество их заказов. Мы добьёмся этого, используя sum агрегацию по полям total_quantity и taxless_total_price, max агрегацию по полю total_quantity и cardinality агрегацию по полю order_id:

    Adding multiple aggregations to a transform in Kibana

    Если вас интересует подмножество данных, вы можете необязательно включить элемент запроса. В этом примере мы отфильтровали данные, чтобы рассматривать только заказы с 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"
            }
          }
        }
      }
    }
  4. Когда вы будете удовлетворены тем, что видите в предварительном просмотре, создайте преобразование.

    1. Укажите идентификатор преобразования, имя индекса назначения и, необязательно, описание. Если индекс назначения не существует, он будет автоматически создан при запуске преобразования.
    2. Решите, хотите ли вы, чтобы преобразование выполнялось один раз или непрерывно. Поскольку этот индекс с данными примера не меняется, давайте воспользуемся стандартным поведением и выполним преобразование один раз. Однако, если вы хотите попробовать, нажмите Непрерывный режим. Вы должны выбрать поле, которое преобразование может использовать для проверки, какие сущности изменились. Как правило, рекомендуется использовать поле отметки времени загрузки. Однако в данном примере вы можете использовать поле order_date.
    3. Необязательно, вы можете настроить политику хранения, которая применяется к вашему преобразованию. Выберите поле даты, используемое для определения старых документов в целевом индексе, и укажите максимальный срок действия. Документы, которые старше заданного значения, удаляются из целевого индекса.
    Adding transfrom ID and retention policy to a transform in Kibana

    В Kibana, прежде чем завершить создание преобразования, вы можете скопировать запрос API преобразования предварительного просмотра в буфер обмена. Эта информация полезна позднее, когда вы решаете, хотите ли вы вручную создать целевой индекс.

    Copy the Dev Console statement of the transform preview to the clipboard

    Если предпочитаете, можете воспользоваться 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"
        }
      }
    }
  5. Необязательно: создайте целевой индекс.

    Если целевой индекс не существует, он создаётся при первом запуске преобразования. Преобразование сворачивания определяет соответствия для целевого индекса на основе исходных индексов и агрегаций преобразования. Если в целевом индексе есть поля, полученные из скриптов (например, если вы используете 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 response
    const 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"
          }
        }
      }
    }
  6. Запустите преобразование.

    Несмотря на то, что использование ресурсов автоматически корректируется в зависимости от нагрузки кластера, преобразование увеличивает нагрузку на поиск и индексирование в кластере во время его выполнения. Однако, если вы столкнётесь с чрезмерной нагрузкой, вы можете остановить его.

    Вы можете запускать, останавливать, сбрасывать и управлять преобразованиями в Kibana:

    Managing transforms in 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

    Если вы выбрали пакетное преобразование, это единственное действие с единственной контрольной точкой. Вы не можете перезапустить его после завершения. Преобразования в непрерывном режиме отличаются тем, что они постоянно увеличивают и обрабатывают контрольные точки по мере добавления новых исходных данных.

  7. Изучите данные в вашем новом индексе.

    Например, используйте приложение Обзор в Kibana:

    Exploring the new index in Kibana
  1. Необязательно: Создайте другой трансформирование, на этот раз используя метод latest.

    Этот метод заполняет индекс назначения последними документами для каждого уникального значения ключа. Например, вы можете найти последние заказы (отсортированные по полю order_date) для каждого клиента или для каждой страны и региона.

    Creating a latest transform in Kibana
    Пример 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 не вычисляют определения сопоставления при создании индекса. Вместо этого они используют динамические сопоставления. Для использования явных сопоставлений создайте индекс назначения перед запуском трансформации.

  2. Если вы не хотите сохранять трансформирование, вы можете удалить его в 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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API