Spec-Zone.ru › Elasticsearch 8
›Elasticsearch Guide [8.17] ›Агрегирования ›Агрегирования по корзинам

Агрегирование Multi Terms

Агрегирование на основе источника значений для нескольких корзин, где корзины создаются динамически — по одному на каждый набор уникальных значений. Агрегирование multi terms очень похоже на terms aggregation, однако в большинстве случаев оно будет медленнее, чем агрегирование terms, и потребует больше памяти. Поэтому, если один и тот же набор полей постоянно используется, будет эффективнее индексировать объединенный ключ для этих полей как отдельное поле и использовать агрегирование terms для этого поля.

Агрегирование multi_term наиболее полезно, когда требуется сортировка по количеству документов или метрическому агрегированию по составному ключу и получению N лучших результатов. Если сортировка не требуется и все значения ожидают получения с помощью вложенного агрегирования terms или composite aggregations, будет более быстрым и эффективным решением с точки зрения памяти.

Пример:

resp = client.search(
    index="products",
    aggs={
        "genres_and_products": {
            "multi_terms": {
                "terms": [
                    {
                        "field": "genre"
                    },
                    {
                        "field": "product"
                    }
                ]
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'products',
  body: {
    aggregations: {
      genres_and_products: {
        multi_terms: {
          terms: [
            {
              field: 'genre'
            },
            {
              field: 'product'
            }
          ]
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "products",
  aggs: {
    genres_and_products: {
      multi_terms: {
        terms: [
          {
            field: "genre",
          },
          {
            field: "product",
          },
        ],
      },
    },
  },
});
console.log(response);
GET /products/_search
{
  "aggs": {
    "genres_and_products": {
      "multi_terms": {
        "terms": [{
          "field": "genre" 
        }, {
          "field": "product"
        }]
      }
    }
  }
}

Агрегирование multi_terms может работать с теми же типами полей, что и terms aggregation, и поддерживает большинство параметров агрегирования terms.

Ответ:

{
  ...
  "aggregations" : {
    "genres_and_products" : {
      "doc_count_error_upper_bound" : 0,  
      "sum_other_doc_count" : 0,          
      "buckets" : [                       
        {
          "key" : [                       
            "rock",
            "Product A"
          ],
          "key_as_string" : "rock|Product A",
          "doc_count" : 2
        },
        {
          "key" : [
            "electronic",
            "Product B"
          ],
          "key_as_string" : "electronic|Product B",
          "doc_count" : 1
        },
        {
          "key" : [
            "jazz",
            "Product B"
          ],
          "key_as_string" : "jazz|Product B",
          "doc_count" : 1
        },
        {
          "key" : [
            "rock",
            "Product B"
          ],
          "key_as_string" : "rock|Product B",
          "doc_count" : 1
        }
      ]
    }
  }
}

верхняя граница ошибки в подсчете документов для каждого термина, см. <<search-aggregations-bucket-multi-terms-aggregation-approximate-counts,ниже>

если есть много уникальных терминов, Elasticsearch возвращает только лучшие термины; это число равно сумме подсчетов документов для всех корзин, которые не входят в ответ

список лучших корзин.

ключи — массивы значений, отсортированные так же, как выражение в параметре terms агрегирования

По умолчанию агрегирование multi_terms вернет корзины для десяти лучших терминов, отсортированные по doc_count. Это поведение можно изменить, установив параметр size.

Параметры агрегирования

Поддерживаются следующие параметры. Подробнее см. terms aggregation.

size

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

shard_size

Необязательно. Чем выше значение запрашиваемого size, тем точнее результаты, но тем дороже будет вычисление конечных результатов. Значение по умолчанию shard_size равно (size * 1.5 + 10).

show_term_doc_count_error

Необязательно. Вычисляет ошибку количества документов для каждого термина. По умолчанию false

order

Необязательно. Указывает порядок корзин. По умолчанию — количество документов на корзину. Значение термина корзины используется в качестве разрыва для корзин с одинаковым количеством документов.

min_doc_count

Необязательно. Минимальное количество документов в корзине для ее возврата. По умолчанию 1.

shard_min_doc_count

Необязательно. Минимальное количество документов в корзине на каждом фрагменте для ее возврата. По умолчанию min_doc_count.

collect_mode

Необязательно. Указывает стратегию сбора данных. Поддерживаются режимы depth_first или breadth_first. По умолчанию breadth_first.

Скрипт

Генерация терминов с помощью скрипта:

resp = client.search(
    index="products",
    runtime_mappings={
        "genre.length": {
            "type": "long",
            "script": "emit(doc['genre'].value.length())"
        }
    },
    aggs={
        "genres_and_products": {
            "multi_terms": {
                "terms": [
                    {
                        "field": "genre.length"
                    },
                    {
                        "field": "product"
                    }
                ]
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'products',
  body: {
    runtime_mappings: {
      'genre.length' => {
        type: 'long',
        script: "emit(doc['genre'].value.length())"
      }
    },
    aggregations: {
      genres_and_products: {
        multi_terms: {
          terms: [
            {
              field: 'genre.length'
            },
            {
              field: 'product'
            }
          ]
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "products",
  runtime_mappings: {
    "genre.length": {
      type: "long",
      script: "emit(doc['genre'].value.length())",
    },
  },
  aggs: {
    genres_and_products: {
      multi_terms: {
        terms: [
          {
            field: "genre.length",
          },
          {
            field: "product",
          },
        ],
      },
    },
  },
});
console.log(response);
GET /products/_search
{
  "runtime_mappings": {
    "genre.length": {
      "type": "long",
      "script": "emit(doc['genre'].value.length())"
    }
  },
  "aggs": {
    "genres_and_products": {
      "multi_terms": {
        "terms": [
          {
            "field": "genre.length"
          },
          {
            "field": "product"
          }
        ]
      }
    }
  }
}

Ответ:

{
  ...
  "aggregations" : {
    "genres_and_products" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : [
            4,
            "Product A"
          ],
          "key_as_string" : "4|Product A",
          "doc_count" : 2
        },
        {
          "key" : [
            4,
            "Product B"
          ],
          "key_as_string" : "4|Product B",
          "doc_count" : 2
        },
        {
          "key" : [
            10,
            "Product B"
          ],
          "key_as_string" : "10|Product B",
          "doc_count" : 1
        }
      ]
    }
  }
}

Пропущенное значение

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

resp = client.search(
    index="products",
    aggs={
        "genres_and_products": {
            "multi_terms": {
                "terms": [
                    {
                        "field": "genre"
                    },
                    {
                        "field": "product",
                        "missing": "Product Z"
                    }
                ]
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'products',
  body: {
    aggregations: {
      genres_and_products: {
        multi_terms: {
          terms: [
            {
              field: 'genre'
            },
            {
              field: 'product',
              missing: 'Product Z'
            }
          ]
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "products",
  aggs: {
    genres_and_products: {
      multi_terms: {
        terms: [
          {
            field: "genre",
          },
          {
            field: "product",
            missing: "Product Z",
          },
        ],
      },
    },
  },
});
console.log(response);
GET /products/_search
{
  "aggs": {
    "genres_and_products": {
      "multi_terms": {
        "terms": [
          {
            "field": "genre"
          },
          {
            "field": "product",
            "missing": "Product Z"
          }
        ]
      }
    }
  }
}

Ответ:

{
   ...
   "aggregations" : {
    "genres_and_products" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : [
            "rock",
            "Product A"
          ],
          "key_as_string" : "rock|Product A",
          "doc_count" : 2
        },
        {
          "key" : [
            "electronic",
            "Product B"
          ],
          "key_as_string" : "electronic|Product B",
          "doc_count" : 1
        },
        {
          "key" : [
            "electronic",
            "Product Z"
          ],
          "key_as_string" : "electronic|Product Z",  
          "doc_count" : 1
        },
        {
          "key" : [
            "jazz",
            "Product B"
          ],
          "key_as_string" : "jazz|Product B",
          "doc_count" : 1
        },
        {
          "key" : [
            "rock",
            "Product B"
          ],
          "key_as_string" : "rock|Product B",
          "doc_count" : 1
        }
      ]
    }
  }
}

Документы без значения в поле product попадут в ту же корзину, что и документы со значением Product Z.

Смешивание типов полей

При агрегировании по нескольким индексам тип агрегированного поля может отличаться в разных индексах. Некоторые типы совместимы друг с другом (integer и long или float и double), но когда типы смешаны (десятичные и не десятичные числа), агрегирование terms преобразует не десятичные числа в десятичные. Это может привести к потере точности значений в корзинах.

Примеры вложенных агрегаций и сортировки

Как и большинство агрегаций по корзинам, multi_term поддерживает вложенные агрегации и сортировку корзин по метрическим вложенным агрегациям:

resp = client.search(
    index="products",
    aggs={
        "genres_and_products": {
            "multi_terms": {
                "terms": [
                    {
                        "field": "genre"
                    },
                    {
                        "field": "product"
                    }
                ],
                "order": {
                    "total_quantity": "desc"
                }
            },
            "aggs": {
                "total_quantity": {
                    "sum": {
                        "field": "quantity"
                    }
                }
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'products',
  body: {
    aggregations: {
      genres_and_products: {
        multi_terms: {
          terms: [
            {
              field: 'genre'
            },
            {
              field: 'product'
            }
          ],
          order: {
            total_quantity: 'desc'
          }
        },
        aggregations: {
          total_quantity: {
            sum: {
              field: 'quantity'
            }
          }
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "products",
  aggs: {
    genres_and_products: {
      multi_terms: {
        terms: [
          {
            field: "genre",
          },
          {
            field: "product",
          },
        ],
        order: {
          total_quantity: "desc",
        },
      },
      aggs: {
        total_quantity: {
          sum: {
            field: "quantity",
          },
        },
      },
    },
  },
});
console.log(response);
GET /products/_search
{
  "aggs": {
    "genres_and_products": {
      "multi_terms": {
        "terms": [
          {
            "field": "genre"
          },
          {
            "field": "product"
          }
        ],
        "order": {
          "total_quantity": "desc"
        }
      },
      "aggs": {
        "total_quantity": {
          "sum": {
            "field": "quantity"
          }
        }
      }
    }
  }
}
{
  ...
  "aggregations" : {
    "genres_and_products" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : [
            "jazz",
            "Product B"
          ],
          "key_as_string" : "jazz|Product B",
          "doc_count" : 1,
          "total_quantity" : {
            "value" : 10.0
          }
        },
        {
          "key" : [
            "rock",
            "Product A"
          ],
          "key_as_string" : "rock|Product A",
          "doc_count" : 2,
          "total_quantity" : {
            "value" : 9.0
          }
        },
        {
          "key" : [
            "electronic",
            "Product B"
          ],
          "key_as_string" : "electronic|Product B",
          "doc_count" : 1,
          "total_quantity" : {
            "value" : 3.0
          }
        },
        {
          "key" : [
            "rock",
            "Product B"
          ],
          "key_as_string" : "rock|Product B",
          "doc_count" : 1,
          "total_quantity" : {
            "value" : 1.0
          }
        }
      ]
    }
  }
}

© 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/search-aggregations-bucket-multi-terms-aggregation.html

Spec-Zone.ru

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