Агрегация редких терминов
Многоуровневая агрегация по источнику значений, которая находит «редкие» термины — термины, которые находятся на длинном хвосте распределения и не являются частыми. По сути, это похоже на агрегацию terms, отсортированную по _count по возрастанию. Как отмечается в документации по агрегации терминов, фактическая сортировка агрегации terms по возрастанию количества имеет неограниченную ошибку. Вместо этого следует использовать агрегацию rare_terms.
Синтаксис
Агрегация rare_terms выглядит следующим образом:
{
"rare_terms": {
"field": "the_field",
"max_doc_count": 1
}
} Таблица 45. Параметры rare_terms
Название параметра | Описание | Обязательно | Значение по умолчанию |
| Поле, в котором мы хотим найти редкие термины | Обязательно | |
| Максимальное количество документов, в которых должен появляться термин. | Необязательно |
|
| Точность внутренних CuckooFilters. Более низкая точность приводит к лучшему приближению, но большему использованию памяти. Не может быть меньше | Необязательно |
|
| Термины, которые должны быть включены в агрегацию | Необязательно | |
| Термины, которые должны быть исключены из агрегации | Необязательно | |
| Значение, которое должно использоваться, если у документа отсутствует поле, которое агрегируется | Необязательно |
Пример:
GET /_search
{
"aggs": {
"genres": {
"rare_terms": {
"field": "genre"
}
}
}
} Ответ:
{
...
"aggregations": {
"genres": {
"buckets": [
{
"key": "swing",
"doc_count": 1
}
]
}
}
} В этом примере единственной группой, которую мы видим, является группа "swing", потому что это единственный термин, который появляется в одном документе. Если мы увеличим max_doc_count до 2, мы увидим больше групп:
GET /_search
{
"aggs": {
"genres": {
"rare_terms": {
"field": "genre",
"max_doc_count": 2
}
}
}
} Теперь отображается термин "jazz", который имеет doc_count значение 2:
{
...
"aggregations": {
"genres": {
"buckets": [
{
"key": "swing",
"doc_count": 1
},
{
"key": "jazz",
"doc_count": 2
}
]
}
}
} Максимальное количество документов
Параметр max_doc_count используется для управления верхней границей количества документов, которые может иметь термин. Нет ограничения размера на агрегацию rare_terms, в отличие от агрегации terms. Это означает, что будут возвращены термины, которые соответствуют критериям max_doc_count. Агрегация выполняется таким образом, чтобы избежать проблем с сортировкой по возрастанию, которые затрагивают агрегацию terms.
Однако это означает, что может быть возвращено большое количество результатов, если выбран неверный параметр. Чтобы ограничить опасность этого параметра, максимальное значение max_doc_count составляет 100.
Максимальное ограничение групп
Агрегация редких терминов больше подвержена срабатыванию мягкого ограничения search.max_buckets, чем другие агрегации, из-за своего принципа работы. Мягкое ограничение max_bucket оценивается по каждому фрагменту (shard) во время сбора результатов агрегации. Возможно, что термин будет «редким» на одном фрагменте, но перестанет быть «редким», как только все результаты фрагментов будут объединены. Это означает, что отдельные фрагменты склонны собирать больше групп, чем на самом деле являются редкими, потому что у них есть только локальный просмотр. Этот список в конечном итоге отсекается до правильного, меньшего списка редких терминов на координационном узле… но фрагмент может уже сработать на мягком ограничении max_buckets и прервать запрос.
При агрегации по полям, которые могут содержать много «редких» терминов, вам может потребоваться увеличить мягкое ограничение max_buckets. В качестве альтернативы, вам может потребоваться найти способ отфильтровать результаты, чтобы вернуть меньше редких значений (меньший временной интервал, фильтрация по категории и т.д.) или пересмотреть определение «редкого» (например, если что-то встречается 100 000 раз, это действительно «редко»?).
Подсчет документов приблизительный
Примитивный способ определения «редких» терминов в наборе данных — поместить все значения в карту, увеличивая счетчики по мере посещения каждого документа, а затем вернуть строки с наименьшими значениями. Это не масштабируется даже с небольшими наборами данных.
Разделенный подход, при котором сохраняются только «n-лучших» значений из каждого фрагмента (как в агрегации terms), терпит неудачу, потому что длинный хвост проблемы означает, что невозможно найти «n-худших» значений без простого сбора всех значений со всех фрагментов.
Вместо этого агрегация редких терминов использует другой приближенный алгоритм:
- Значения помещаются в карту при первом появлении.
- Каждое последующее появление термина увеличивает счетчик в карте.
- Если счетчик превышает порог
max_doc_count, термин удаляется из карты и помещается в CuckooFilter. - CuckooFilter проверяется для каждого термина. Если значение есть в фильтре, оно уже известно как часто встречающееся и пропускается.
После выполнения, карта значений является картой «редких» терминов ниже порога max_doc_count. Затем эта карта и CuckooFilter объединяются со всеми другими фрагментами. Если есть термины, которые превышают порог (или появляются в CuckooFilter другого фрагмента), термин удаляется из объединенного списка. Конечная карта значений возвращается пользователю как «редкие» термины.
CuckooFilters могут иметь ложноположительные результаты (они могут указывать на существование значения в их коллекции, когда оно на самом деле отсутствует). Поскольку CuckooFilter используется для проверки, превышает ли термин порог, это означает, что ложноположительный результат из CuckooFilter ошибочно указывает на распространенность значения, когда оно не является таковым (и, следовательно, исключает его из окончательного списка групп). Практически это означает, что агрегация демонстрирует ложноотрицательный результат, поскольку фильтр используется «в обратном» порядке, чем обычно представляют себе люди.
CuckooFilters описаны более подробно в статье:
Fan, Bin, et al. "Cuckoo filter: Practically better than bloom." Труды 10-й международной конференции ACM по экспериментам в области новых сетей и технологиям. ACM, 2014.
Точность
Хотя внутренний CuckooFilter по своей природе приблизительный, уровень ложноотрицательных результатов можно контролировать с помощью параметра precision. Это позволяет пользователю обменять больше оперативной памяти на более точные результаты.
По умолчанию точность равна 0.001, а наименьшая (т.е. наиболее точная и наибольшая нагрузка на память) равна 0.00001. Ниже приведены некоторые диаграммы, которые демонстрируют, как точность агрегации зависит от точности и количества уникальных терминов.
Ось X показывает количество уникальных значений, которые видела агрегация, а ось Y — процентную ошибку. Каждая линия серии соответствует одному условию «редкости» (от одного редкого элемента до 100 000 редких элементов). Например, оранжевая линия «10» означает, что десять значений были «редкими» (doc_count == 1), из 1–20 млн уникальных значений (при этом остальные значения имели doc_count > 1).
На первой диаграмме показана точность 0.01:
А также точность 0.001 (значение по умолчанию):
И, наконец, precision 0.0001:
Точность по умолчанию 0.001 поддерживает точность < 2,5% для протестированных условий, а точность медленно снижается контролируемым линейным способом по мере увеличения количества уникальных значений.
Точность по умолчанию 0.001 имеет профиль памяти 1.748⁻⁶ * n байт, где n — количество уникальных значений, которые видела агрегация (также можно примерно оценить, например, 20 миллионов уникальных значений примерно 30 МБ памяти). Использование памяти линейно зависит от количества уникальных значений независимо от выбранной точности, точность только влияет на наклон профиля памяти, как показано на этой диаграмме:
Для сравнения, эквивалентная агрегация терминов на 20 миллионах групп будет примерно 20m * 69b == ~1.38gb (при том, что 69 байт — очень оптимистичная оценка стоимости пустой группы, значительно меньше, чем учитывает разрывающий механизм). Таким образом, хотя агрегация rare_terms относительно ресурсоемкая, она всё ещё на несколько порядков меньше, чем эквивалентная агрегация терминов.
Фильтрация значений
Можно отфильтровать значения, для которых будут созданы корзины. Это можно сделать, используя параметры include и exclude, основанные на строках регулярных выражений или массивах точных значений. Кроме того, клаузы include могут фильтровать с использованием выражений partition.
Фильтрация значений с помощью регулярных выражений
GET /_search
{
"aggs": {
"genres": {
"rare_terms": {
"field": "genre",
"include": "swi*",
"exclude": "electro*"
}
}
}
} В приведенном выше примере корзины будут созданы для всех тегов, начинающихся с swi, за исключением тех, которые начинаются с electro (так что тег swing будет агрегирован, но не electro_swing). Регулярное выражение include определит, какие значения «разрешено» агрегировать, а exclude определит значения, которые не следует агрегировать. При определении обоих, у exclude имеет приоритет, что означает, что include оценивается первой, а только затем exclude.
Синтаксис аналогичен запросам регулярных выражений.
Фильтрация значений с точными значениями
Для соответствия на основе точных значений параметры include и exclude могут просто принимать массив строк, представляющих термины в том виде, как они встречаются в индексе:
GET /_search
{
"aggs": {
"genres": {
"rare_terms": {
"field": "genre",
"include": [ "swing", "rock" ],
"exclude": [ "jazz" ]
}
}
}
} Отсутствующее значение
Параметр missing определяет, как должны обрабатываться документы, у которых отсутствует значение. По умолчанию они будут игнорироваться, но также можно рассматривать их так, как будто у них есть значение.
GET /_search
{
"aggs": {
"genres": {
"rare_terms": {
"field": "genre",
"missing": "N/A"
}
}
}
} | Документы без значения в поле |
Вложенные, RareTerms и под-агрегации scoring
Агрегация RareTerms должна работать в режиме breadth_first, так как ей необходимо обрезать термины, по мере превышения пороговых значений количества документов. Это требование означает, что агрегация RareTerms несовместима с определенными сочетаниями агрегаций, которые требуют depth_first. В частности, под-агрегации scoring, которые находятся внутри nested, вынуждают всю древовидную структуру агрегации работать в режиме depth_first. Это приведет к исключению, так как RareTerms не может обработать depth_first.
В качестве конкретного примера, если агрегация rare_terms является дочерней агрегацией nested, а одна из дочерних агрегаций rare_terms нуждается в оценках документов (например, агрегация top_hits), это приведет к исключению.
© 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/7.17/search-aggregations-bucket-rare-terms-aggregation.html