Агрегация - это способ группировки и извлечения статистики из ваших данных. Если вы знакомы с реляционными базами данных, вы можете считать это эквивалентом пункта GROUP BY в SQL и агрегатных функций, таких как SUM. Интересно, что Elasticsearch предоставляет довольно мощную функцию, которая позволяет выполнять поиск и возвращать результаты как обычно, но одновременно возвращать агрегированные результаты. Эти агрегированные результаты отделены от результатов поиска, и все они могут быть возвращены в одном запросе, что позволяет избежать многочисленных сетевых обходов.
Существует три типа агрегации: метрическая, ведерная и конвейерная. Конвейерные агрегации являются экспериментальными и предназначены для довольно сложных случаев использования, поэтому я не буду рассказывать об этом в данной статье, так как функциональность, скорее всего, изменится. Метрические агрегации работают со значениями, извлеченными из агрегированных документов. Эти значения обычно извлекаются из определенного поля документа, которое указывается в запросе. Можно также получить больше контроля и возвращать значения из сценария, но это выходит за рамки данной статьи. Большинство агрегаций метрик выводят одну числовую метрику, например агрегация суммы, и называются агрегациями числовых метрик с одним значением. Другие, которые генерируют несколько метрик, например, агрегация stats, называются многозначными числовыми метрическими агрегациями. Это звучит сложнее, чем есть на самом деле, поэтому не стоит слишком беспокоиться об этом, потому что сейчас я покажу вам примеры.
Самый простой для понимания агрегат - это агрегат суммы. Эта агрегация по одной метрике суммирует числовые значения, которые извлекаются из агрегированных документов. Давайте напишем простой запрос, который суммирует общее количество всех товаров в индексе электронной коммерции.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | GET /ecommerce/product/_search { "query": { "match_all": { } }, "size": 0, "aggs": { "quantity_sum": { "sum": { "field": "quantity" } } } } |
Ключ aggs также может быть именованным агрегатом, если вы предпочитаете. quantity_sum - это имя агрегата, а sum - тип агрегата.
Поскольку я использую запрос match_all, в агрегации используются все товары. Давайте попробую немного изменить запрос и посмотрим, какое количество будет у всех макаронных изделий.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | GET /ecommerce/product/_search { "query": { "match": { "name": { "query": "pasta" } } }, "size": 0, "aggs": { "quantity_sum": { "sum": { "field": "quantity" } } } } |
Агрегированное количество теперь меньше, потому что в агрегации используются только макаронные изделия.
Другой агрегацией по одной метрике является агрегация avg, которая вычисляет среднее значение для поля документа. Я просто немного изменю запрос.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | GET /ecommerce/product/_search { "query": { "match": { "name": { "запрос": "pasta" } } }, "size": 0, "aggs": { "avg_quantity": { "avg": { "поле": "quantity" } } } } |
Теперь этот запрос вычисляет среднее количество для всех макаронных изделий.
Еще два агрегата - это агрегаты min и max, которые вычисляют наименьшее и наибольшее значение для поля документа соответственно. Я лишь слегка изменю запрос, чтобы использовать агрегацию min.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | GET /ecommerce/product/_search { "query": { "match": { "name": { "query": "pasta" } } }, "size": 0, "aggs": { "min_quantity": { "min": { "field": "quantity" } } } } |
Как показывают результаты, наименьшее значение для поля количества - два для всех макаронных изделий. Как вы уже догадались, для использования запроса max достаточно заменить тип агрегации min на max.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | GET /ecommerce/product/_search { "query": { "match": { "name": { "query": "pasta" } } }, "size": 0, "aggs": { "max_quantity": { "max": { "field": "quantity" } } } } |
На этот раз результаты показывают, что максимальное значение для поля quantity равно 87.
Эти агрегации были так называемыми однозначными агрегациями, потому что они выводят только одно значение. Давайте теперь перейдем к рассмотрению многозначной агрегации, а именно агрегации статистики. Этот агрегатор вычисляет статистику по агрегированным документам. Фактически, эта статистика включает в себя агрегации, которые я только что показал вам.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | GET /ecommerce/product/_search { "query": { "match": { "name": { "query": "pasta" } } }, "size": 0, "aggs": { "quantity_stats": { "stats": { "field": "quantity" } } } } |
Это многозначная агрегация, просто потому что она возвращает несколько значений. Глядя на результаты, мы видим, что возвращается количество документов, а также минимальное, максимальное и среднее значение для поля. Сумма всех значений для поля также рассчитывается и возвращается.
Существуют и другие агрегации метрик, но это самые важные. Если вам нужен полный список доступных агрегаций метрик, загляните в документацию.
Теперь, когда я обсудил агрегации метрик, я перейду к агрегациям ведер, которые немного сложнее. Вместо вычисления метрик по полям, агрегации ведер создают ведра или наборы документов. Каждое ведро связано с критерием, которому должны удовлетворять документы, чтобы быть частью этого ведра. Это нелегко понять без примера, поэтому позвольте мне показать вам именно это.
В этом примере я буду использовать агрегацию по диапазону, которая позволяет мне группировать документы вместе на основе диапазонов для поля количества, как вы увидите через мгновение, когда я введу запрос.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | GET /ecommerce/product/_search { "query": { "match_all": { } }, "size": 0, "aggs": { "quantity_ranges": { "range": { "field": "quantity", "ranges": [ { "from": 1, "to": 50 }, { "from": 50, "to": 100 } ] } } } } |
Обратите внимание, что для каждого диапазона значение "от" включено, а значение "до" исключено. В результатах мы видим, что 483 документа имеют количество в диапазоне 1-50, а 506 документов относятся к диапазону 50-100. Примером использования этой агрегации может быть поиск количества продуктов в определенных ценовых диапазонах, что позволяет пользователю применить фильтр для заданного ценового диапазона.
Интересной особенностью, доступной для агрегаций ведер, является возможность добавления подагрегаций, что невозможно для метрических агрегаций. При этом агрегация будет объединять документы, находящиеся в ведрах, которые создала родительская агрегация ведер. Надеюсь, это не звучит слишком запутанно, но не волнуйтесь, если это так, потому что сейчас я приведу вам пример.
Допустим, я хочу получить статистику по документам в каждом ведре. Для этого я могу добавить подагрегацию типа stats, которая на самом деле является метрической агрегацией, которую я показывал вам минуту назад. Эта метрическая агрегация затем будет работать с документами, которые содержатся в ведре, созданном агрегацией диапазона. Давайте посмотрим на это в действии.
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 | GET /ecommerce/product/_search { "query": { "match_all": { } }, "size": 0, "aggs": { "quantity_ranges": { "range": { "field": "quantity", "ranges": [ { "from": 1, "to": 50 }, { "from": 50, "to": 100 } ] }, "aggs": { "quantity_stats": { "stats": { "field": "quantity" } } } } } } |
Теперь результаты включают статистику для документов в каждом ведре, поэтому агрегация статистики выполняется в контексте каждого из ведер. Вы можете даже вложить агрегаты еще дальше, хотя обычно вам это не нужно. Например, можно добавить под-агрегацию для дальнейшего деления диапазонов количества, а затем добавить еще одну под-агрегацию типа stats, чтобы получить статистику для каждого из этих диапазонов. На самом деле, нет жестких ограничений на то, как глубоко вы можете вложить агрегаты, но, конечно, производительность будет снижаться по мере увеличения количества добавлений.
Существует довольно много агрегаций ведер, но перечисление их всех займет много времени, а вы, вероятно, не захотите слушать, как я часами рассказываю об этом, поэтому я просто упомяну еще одну полезную агрегацию ведер. Агрегация терминов создает ведро для каждого уникального термина для данного поля. Это может быть полезно для поля пола, содержащего либо Male, либо Female, потому что это может быть использовано для подсчета количества людей каждого пола в индексе. Это довольно полезно, поэтому я собираюсь показать вам, как использовать эту агрегацию в одной из последующих лекций при создании образца поисковой системы.
Это все, что я хотел рассказать вам об агрегации. Как я уже сказал, существует довольно много агрегаций, которые я не рассмотрел в этой статье, но я обсудил самые важные из них, которые вам необходимо знать. Остальные относятся к граничным случаям использования, поэтому вероятность того, что вы столкнетесь с ними, гораздо ниже.