Агрегация значимых терминов
Агрегация, возвращающая интересные или необычные появления терминов в наборе.
Примеры использования:
- Предложение "H5N1" при поиске пользователей по запросу "птичий грипп" в тексте
- Определение продавца, который является "общей точкой компрометации" из истории транзакций владельцев кредитных карт, которые сообщили о потере
- Предложение ключевых слов, относящихся к символу акций $ATI, для автоматизированного классификатора новостей
- Выявление мошеннического врача, который диагностирует больше, чем положено, случаев травм шейного отдела позвоночника
- Выявление производителя шин, у которого наблюдается непропорционально большое количество проколов
Во всех этих случаях выбираемые термины — не просто самые популярные термины в наборе. Это термины, которые претерпели значительные изменения в популярности, измеренные между фоновым и фоновым наборами. Если термин «H5N1» существует только в 5 документах в индексе из 10 миллионов документов, но встречается в 4 из 100 документов, составляющих результаты поиска пользователя, это значимо и, вероятно, очень актуально для его поиска. 5/10 000 000 против 4/100 — это большой скачок частоты.
Анализ одного набора
В самом простом случае фоновый набор — это результаты поиска, соответствующие запросу, а фоновый набор, используемый для статистических сравнений, — это индекс или индексы, из которых были получены результаты.
Пример:
resp = client.search(
query={
"terms": {
"force": [
"British Transport Police"
]
}
},
aggregations={
"significant_crime_types": {
"significant_terms": {
"field": "crime_type"
}
}
},
)
print(resp) response = client.search(
body: {
query: {
terms: {
force: [
'British Transport Police'
]
}
},
aggregations: {
significant_crime_types: {
significant_terms: {
field: 'crime_type'
}
}
}
}
)
puts response const response = await client.search({
query: {
terms: {
force: ["British Transport Police"],
},
},
aggregations: {
significant_crime_types: {
significant_terms: {
field: "crime_type",
},
},
},
});
console.log(response); GET /_search
{
"query": {
"terms": { "force": [ "British Transport Police" ] }
},
"aggregations": {
"significant_crime_types": {
"significant_terms": { "field": "crime_type" }
}
}
} Ответ:
{
...
"aggregations": {
"significant_crime_types": {
"doc_count": 47347,
"bg_count": 5064554,
"buckets": [
{
"key": "Bicycle theft",
"doc_count": 3640,
"score": 0.371235374214817,
"bg_count": 66799
}
...
]
}
}
} При запросе к индексу всех преступлений всех полицейских сил эти результаты показывают, что Британская транспортная полиция выделяется как сила, занимающаяся непропорционально большим количеством краж велосипедов. Обычно кражи велосипедов составляют всего 1% преступлений (66799/5064554), но для Британской транспортной полиции, которая занимается преступлениями на железных дорогах и станциях, кражи велосипедов составляют 7% преступлений (3640/47347). Это значительное увеличение частоты в семь раз, поэтому эта аномалия была выделена как тип преступления с наивысшим приоритетом.
Проблема использования запроса для выявления аномалий заключается в том, что он предоставляет нам только один подмножество для сравнения. Чтобы обнаружить все остальные аномалии полицейских сил, нам пришлось бы повторять запрос для каждой из этих сил.
Это может быть утомительным способом поиска необычных закономерностей в индексе.
Анализ нескольких наборов
Более простой способ анализа по нескольким категориям — использовать агрегацию на родительском уровне для сегментации данных, подготовленных для анализа.
Пример с использованием агрегации родительского уровня для сегментации:
resp = client.search(
aggregations={
"forces": {
"terms": {
"field": "force"
},
"aggregations": {
"significant_crime_types": {
"significant_terms": {
"field": "crime_type"
}
}
}
}
},
)
print(resp) response = client.search(
body: {
aggregations: {
forces: {
terms: {
field: 'force'
},
aggregations: {
significant_crime_types: {
significant_terms: {
field: 'crime_type'
}
}
}
}
}
}
)
puts response const response = await client.search({
aggregations: {
forces: {
terms: {
field: "force",
},
aggregations: {
significant_crime_types: {
significant_terms: {
field: "crime_type",
},
},
},
},
},
});
console.log(response); GET /_search
{
"aggregations": {
"forces": {
"terms": { "field": "force" },
"aggregations": {
"significant_crime_types": {
"significant_terms": { "field": "crime_type" }
}
}
}
}
} Ответ:
{
...
"aggregations": {
"forces": {
"doc_count_error_upper_bound": 1375,
"sum_other_doc_count": 7879845,
"buckets": [
{
"key": "Metropolitan Police Service",
"doc_count": 894038,
"significant_crime_types": {
"doc_count": 894038,
"bg_count": 5064554,
"buckets": [
{
"key": "Robbery",
"doc_count": 27617,
"score": 0.0599,
"bg_count": 53182
}
...
]
}
},
{
"key": "British Transport Police",
"doc_count": 47347,
"significant_crime_types": {
"doc_count": 47347,
"bg_count": 5064554,
"buckets": [
{
"key": "Bicycle theft",
"doc_count": 3640,
"score": 0.371,
"bg_count": 66799
}
...
]
}
}
]
}
}
} Теперь мы можем обнаруживать аномалии для каждой из полицейских сил с помощью одного запроса.
Мы можем использовать другие виды агрегаций верхнего уровня для сегментации наших данных, например, сегментацию по географическому региону для выявления необычных концентраций определенного типа преступлений:
resp = client.search(
aggs={
"hotspots": {
"geohash_grid": {
"field": "location",
"precision": 5
},
"aggs": {
"significant_crime_types": {
"significant_terms": {
"field": "crime_type"
}
}
}
}
},
)
print(resp) response = client.search(
body: {
aggregations: {
hotspots: {
geohash_grid: {
field: 'location',
precision: 5
},
aggregations: {
significant_crime_types: {
significant_terms: {
field: 'crime_type'
}
}
}
}
}
}
)
puts response const response = await client.search({
aggs: {
hotspots: {
geohash_grid: {
field: "location",
precision: 5,
},
aggs: {
significant_crime_types: {
significant_terms: {
field: "crime_type",
},
},
},
},
},
});
console.log(response); GET /_search
{
"aggs": {
"hotspots": {
"geohash_grid": {
"field": "location",
"precision": 5
},
"aggs": {
"significant_crime_types": {
"significant_terms": { "field": "crime_type" }
}
}
}
}
} В этом примере используется агрегация geohash_grid для создания корзин результатов, представляющих географические области, и внутри каждой корзины мы можем определить аномальные уровни определенного типа преступлений в этих узконаправленных областях, например:
- Аэропорты демонстрируют необычное число изъятых оружия
- В университетах наблюдается всплеск краж велосипедов
На более высоком уровне детализации geohash_grid с более обширными зонами охвата мы начнем видеть, где вся полицейская сила может бороться с необычно высоким объёмом определённого типа преступлений.
Конечно, сегментация на основе времени поможет определить текущие тенденции для каждого момента времени, где простая агрегация terms обычно показывает очень популярные «константы», которые сохраняются во всех временных интервалах.
Использование на свободных текстовых полях
Агрегация significant_terms может быть эффективно использована на токенизированных свободных текстовых полях для:
- предложения ключевых слов для уточнения поисков конечных пользователей
- предложения ключевых слов для использования в запросах percolator
Выбор свободного текстового поля в качестве объекта анализа значимых терминов может быть дорогостоящим! Он попытается загрузить каждое уникальное слово в ОЗУ. Рекомендуется использовать это только с меньшими индексами.
Отображение significant_terms в контекстеСвободные текстовые significant_terms гораздо легче понять, когда их видят в контексте. Возьмите результаты предложений significant_terms из свободного текстового поля и используйте их в запросе terms на том же поле с клаузой highlight, чтобы предоставить пользователям примеры фрагментов документов. Когда термины представлены без стема, выделены, с правильным регистром, в правильном порядке и с некоторым контекстом, их значимость/значение более очевидны.
Пользовательские фоновые наборы
Обычно набор документов переднего плана «дифференцируется» от фонового набора всех документов в вашем индексе. Однако иногда может оказаться полезным использование более узкого фонового набора в качестве основы для сравнения. Например, запрос по документам, относящимся к «Мадриду», в индексе с контентом со всего мира может показать, что «испанский» — значимый термин. Это может быть правдой, но если вы хотите более конкретные термины, вы можете использовать background_filter по термину испания, чтобы создать более узкий набор документов в качестве контекста. С этим фоновым набором «испанский» теперь будет считаться обычным и, следовательно, не таким значимым, как слова, которые сильнее связаны с Мадридом, например «столица». Обратите внимание, что использование фильтра фона замедлит процесс — теперь частота каждого термина в фоновом наборе должна вычисляться в режиме реального времени путем фильтрации списков публикаций, а не путем чтения предварительно вычисленного подсчета термина в индексе.
Ограничения
Значимые термины должны быть индексированными значениями
В отличие от агрегации терминов, в настоящее время невозможно использовать сгенерированные скриптом термины для подсчёта. Из-за того, как агрегация significant_terms должна учитывать частоты фоновых и передних планов, использование скрипта для всего индекса для получения фоновых частот для сравнения было бы чрезмерно затратным. Также DocValues не поддерживаются в качестве источников данных для терминов по аналогичным причинам.
Отсутствие анализа полей с плавающей точкой
Поля с плавающей точкой в настоящее время не поддерживаются в качестве объекта анализа significant_terms. В то время как поля целого или длинного типа могут быть использованы для представления концепций, таких как номера счетов или номера категорий, которые могут быть интересны для отслеживания, поля с плавающей точкой обычно используются для представления количеств чего-либо. Таким образом, отдельные термины с плавающей точкой не подходят для этого вида анализа частоты.
Использование в качестве родительской агрегации
Если существует эквивалент запроса match_all или нет критериев запроса, предоставляющих подмножество индекса, агрегация significant_terms не должна использоваться как верхняя агрегация — в этом случае множество переднего плана точно такое же, как множество заднего плана, и поэтому нет различий в частотах документов для наблюдения и вывода разумных предложений.
Другой момент заключается в том, что агрегация significant_terms производит множество кандидатов на уровне фрагмента, которые только позже отбрасываются на узле сокращения после объединения всех статистических данных со всех фрагментов. В результате, встраивание больших дочерних агрегаций под агрегацией significant_terms, которая позже отбрасывает многие кандидаты в термины, может быть неэффективным и дорогостоящим с точки зрения оперативной памяти. В таких случаях рекомендуется выполнить два поиска: первый для получения рационализированного списка significant_terms, а затем добавить этот сокращённый список терминов во второй запрос для получения необходимых дочерних агрегаций.
Приблизительные подсчёты
Подсчёты того, сколько документов содержат термин, представленный в результатах, основаны на суммировании выборок, возвращаемых с каждого фрагмента, и поэтому могут быть:
- низкими, если определённые фрагменты не предоставили данных для данного термина в своей верхней выборке
- высокими при рассмотрении фоновой частоты, так как она может учитывать случаи, найденные в удалённых документах
Как и большинство решений, это основа компромисса, в котором мы выбрали быструю производительность ценой некоторой (как правило, небольшой) неточности. Однако параметры size и shard size, рассмотренные в следующем разделе, предоставляют инструменты для управления уровнями точности.
Параметры
Счёт JLH
Счёт JLH можно использовать в качестве показателя значимости, добавив параметр
"jlh": {
} Значения рассчитываются на основе частоты документа в наборах фоновый и передний. Абсолютное изменение популярности (foregroundPercent - backgroundPercent) отдаёт предпочтение общим терминам, а относительное изменение популярности (foregroundPercent/ backgroundPercent) — редким терминам. Редкие и общие термины по сути представляют собой баланс точности и полноты, поэтому абсолютные и относительные изменения перемножаются, чтобы найти оптимальное значение между точностью и полнотой.
Взаимная информация
Взаимную информацию, как описано в «Поиске информации», Manning et al., глава 13.5.1, можно использовать в качестве показателя значимости, добавив параметр
"mutual_information": {
"include_negatives": true
} Взаимная информация не различает термины, которые описывают подмножество или документы за пределами подмножества. Поэтому значимые термины могут содержать термины, которые встречаются чаще или реже в подмножестве, чем за его пределами. Чтобы отфильтровать термины, которые встречаются реже в подмножестве, чем в документах за пределами подмножества, можно установить include_negatives в значение false.
По умолчанию предполагается, что документы в корзине также содержатся в фоновом наборе. Если вы определили пользовательский фильтр фонового набора, представляющий собой другой набор документов, с которым вы хотите сравнить, установите
"background_is_superset": false
Критерий хи-квадрат
Критерий хи-квадрат, как описано в «Поиске информации», Manning et al., глава 13.5.2, можно использовать в качестве показателя значимости, добавив параметр
"chi_square": {
} Критерий хи-квадрат ведёт себя как взаимная информация и может настраиваться с теми же параметрами include_negatives и background_is_superset.
Нормализованное расстояние Google
Нормализованное расстояние Google, как описано в "The Google Similarity Distance", Cilibrasi and Vitanyi, 2007, можно использовать в качестве показателя значимости, добавив параметр
"gnd": {
} gnd также принимает параметр background_is_superset.
Счёт p-значения
p-значение — это вероятность получения результатов теста, по крайней мере, столь же экстремальных, как и фактически наблюдаемые, при условии, что нулевая гипотеза верна. p-значение рассчитывается в предположении, что наборы «передний» и «фоновый» являются независимыми испытаниями Бернулли с нулевой гипотезой, что вероятности одинаковы.
Пример использования
В этом примере вычисляется p-значение для терминов user_agent.version, учитывая передний набор «окончился неудачей» против «НЕ закончился неудачей».
"background_is_superset": false указывает, что фоновый набор не содержит подсчётов переднего набора, поскольку они отфильтрованы.
"normalize_above": 1000 обеспечивает возвращение согласованных результатов значимости в различных масштабах. 1000 указывает, что количество появлений терминов, превышающих 1000, уменьшается в 1000/term_count раз.
resp = client.search(
query={
"bool": {
"filter": [
{
"term": {
"event.outcome": "failure"
}
},
{
"range": {
"@timestamp": {
"gte": "2021-02-01",
"lt": "2021-02-04"
}
}
},
{
"term": {
"service.name": {
"value": "frontend-node"
}
}
}
]
}
},
aggs={
"failure_p_value": {
"significant_terms": {
"field": "user_agent.version",
"background_filter": {
"bool": {
"must_not": [
{
"term": {
"event.outcome": "failure"
}
}
],
"filter": [
{
"range": {
"@timestamp": {
"gte": "2021-02-01",
"lt": "2021-02-04"
}
}
},
{
"term": {
"service.name": {
"value": "frontend-node"
}
}
}
]
}
},
"p_value": {
"background_is_superset": False,
"normalize_above": 1000
}
}
}
},
)
print(resp) response = client.search(
body: {
query: {
bool: {
filter: [
{
term: {
'event.outcome' => 'failure'
}
},
{
range: {
"@timestamp": {
gte: '2021-02-01',
lt: '2021-02-04'
}
}
},
{
term: {
'service.name' => {
value: 'frontend-node'
}
}
}
]
}
},
aggregations: {
failure_p_value: {
significant_terms: {
field: 'user_agent.version',
background_filter: {
bool: {
must_not: [
{
term: {
'event.outcome' => 'failure'
}
}
],
filter: [
{
range: {
"@timestamp": {
gte: '2021-02-01',
lt: '2021-02-04'
}
}
},
{
term: {
'service.name' => {
value: 'frontend-node'
}
}
}
]
}
},
p_value: {
background_is_superset: false,
normalize_above: 1000
}
}
}
}
}
)
puts response const response = await client.search({
query: {
bool: {
filter: [
{
term: {
"event.outcome": "failure",
},
},
{
range: {
"@timestamp": {
gte: "2021-02-01",
lt: "2021-02-04",
},
},
},
{
term: {
"service.name": {
value: "frontend-node",
},
},
},
],
},
},
aggs: {
failure_p_value: {
significant_terms: {
field: "user_agent.version",
background_filter: {
bool: {
must_not: [
{
term: {
"event.outcome": "failure",
},
},
],
filter: [
{
range: {
"@timestamp": {
gte: "2021-02-01",
lt: "2021-02-04",
},
},
},
{
term: {
"service.name": {
value: "frontend-node",
},
},
},
],
},
},
p_value: {
background_is_superset: false,
normalize_above: 1000,
},
},
},
},
});
console.log(response); GET /_search
{
"query": {
"bool": {
"filter": [
{
"term": {
"event.outcome": "failure"
}
},
{
"range": {
"@timestamp": {
"gte": "2021-02-01",
"lt": "2021-02-04"
}
}
},
{
"term": {
"service.name": {
"value": "frontend-node"
}
}
}
]
}
},
"aggs": {
"failure_p_value": {
"significant_terms": {
"field": "user_agent.version",
"background_filter": {
"bool": {
"must_not": [
{
"term": {
"event.outcome": "failure"
}
}
],
"filter": [
{
"range": {
"@timestamp": {
"gte": "2021-02-01",
"lt": "2021-02-04"
}
}
},
{
"term": {
"service.name": {
"value": "frontend-node"
}
}
}
]
}
},
"p_value": {"background_is_superset": false, "normalize_above": 1000}
}
}
}
} Процент
Простая вычисление количества документов в переднем образце с термином, делённое на количество документов в фоновом образце с термином. По умолчанию это даёт значение больше нуля и меньше единицы.
Преимущества этого эвристического подхода заключаются в простоте объяснения для любого человека, знакомого с «поголовной» статистикой. Однако в областях с высокой кардинальностью существует тенденция выбора самых редких терминов, таких как опечатки, которые встречаются только один раз, поскольку они оцениваются как 1/1 = 100%.
Опытному боксёру будет трудно выиграть чемпионат, если награда будет присуждаться только на основе процента выигранных боёв — по этим правилам новичок с только одним боем в своём послужном списке будет непобедим. Для подтверждения мнения обычно требуется несколько наблюдений, поэтому в таких случаях рекомендуется установить и min_doc_count, и shard_min_doc_count на более высокое значение, например, 10, чтобы отфильтровать термины с низкой частотой, которые в противном случае имеют приоритет.
"percentage": {
} Какой из них лучший?
Примерно, mutual_information отдает предпочтение терминам с высокой частотой, даже если они также часто встречаются в фоновом наборе. Например, в анализе текстов естественного языка это может привести к выбору стоп-слов. mutual_information маловероятно выберет очень редкие термины, такие как опечатки. gnd отдает предпочтение терминам с высокой частотой совместного появления и избегает выбора стоп-слов. Он может быть лучше подходит для обнаружения синонимов. Однако, gnd имеет тенденцию выбирать очень редкие термины, которые, например, являются результатом опечатки. chi_square и jlh находятся где-то посередине.
Трудно сказать, какой из различных эвристических подходов будет лучшим выбором, так как это зависит от того, для чего используются значимые термины (см., например, Yang and Pedersen, «Comparative Study on Feature Selection in Text Categorization», 1997 для исследования использования значимых терминов для выбора признаков для классификации текста).
Если ни один из вышеперечисленных показателей не подходит для вашего случая, можно реализовать пользовательский показатель значимости:
Скрипт
Пользовательские метрики могут быть реализованы через скрипт:
"script_heuristic": {
"script": {
"lang": "painless",
"source": "params._subset_freq/(params._superset_freq - params._subset_freq + 1)"
}
} Скрипты могут быть встроенными (как в примере выше), индексированными или сохранёнными на диске. Более подробную информацию об опциях см. в документации по скриптам.
Доступные параметры в скрипте:
| | Количество документов, в которых встречается термин в подмножестве. |
| | Количество документов, в которых встречается термин в надмножестве. |
| | Количество документов в подмножестве. |
| | Количество документов в надмножестве. |
Размер и Размер фрагмента
Параметр size можно установить, чтобы определить, сколько корзин терминов должно быть возвращено из общего списка терминов. По умолчанию узел, координирующий процесс поиска, запросит каждый фрагмент, чтобы получить собственные лучшие корзины терминов, а после получения ответов от всех фрагментов уменьшит результаты до окончательного списка, который затем будет возвращён клиенту. Если количество уникальных терминов больше, чем size, возвращённый список может быть несколько неточным (счётчик терминов может отличаться на несколько единиц, и даже термин, который должен был быть в верхних корзинках, может отсутствовать).
Для повышения точности используется кратное окончательному значению size в качестве количества терминов, которые необходимо запросить у каждого фрагмента (2 * (size * 1.5 + 10)). Для ручного управления этим параметром можно использовать параметр shard_size, чтобы контролировать объём кандидатов на термины, генерируемых каждым фрагментом.
Термины с низкой частотой могут оказаться наиболее интересными после объединения всех результатов, поэтому агрегация significant_terms может генерировать результаты более высокого качества, когда параметр shard_size установлен на значениях, существенно превышающих значение параметра size. Это гарантирует, что большее количество многообещающих кандидатов на термины будут совместно проанализированы узлом сворачивания до окончательного выбора. Очевидно, что большие списки кандидатов на термины приведут к увеличению сетевого трафика и использования оперативной памяти, поэтому это компромисс между качеством и стоимостью, который необходимо сбалансировать. Если shard_size установлен в -1 (значение по умолчанию), то shard_size будет автоматически оцениваться на основе количества фрагментов и параметра size.
shard_size не может быть меньше, чем size (так как это не имеет большого смысла). В этом случае Elasticsearch переопределит его и установит равным size.
Минимальное количество документов
Возможна настройка возврата только тех терминов, которые соответствуют более чем заданному числу совпадений, с помощью опции min_doc_count:
resp = client.search(
aggs={
"tags": {
"significant_terms": {
"field": "tag",
"min_doc_count": 10
}
}
},
)
print(resp) response = client.search(
body: {
aggregations: {
tags: {
significant_terms: {
field: 'tag',
min_doc_count: 10
}
}
}
}
)
puts response const response = await client.search({
aggs: {
tags: {
significant_terms: {
field: "tag",
min_doc_count: 10,
},
},
},
});
console.log(response); GET /_search
{
"aggs": {
"tags": {
"significant_terms": {
"field": "tag",
"min_doc_count": 10
}
}
}
} Вышеприведённая агрегация вернёт только те теги, которые были найдены в 10 и более совпадениях. Значение по умолчанию — 3.
Термины, получившие высокие баллы, будут собраны на уровне фрагмента и объединены с терминами, собранными из других фрагментов на втором этапе. Однако фрагмент не имеет информации о глобальных частотах терминов. Решение о добавлении термина в список кандидатов зависит только от оценки, вычисленной на фрагменте с использованием локальных частот фрагмента, а не глобальных частот слова. Критерий min_doc_count применяется только после объединения статистических данных локальных терминов всех фрагментов. Таким образом, решение о добавлении термина в качестве кандидата принимается, не имея полной уверенности в том, что термин действительно достигнет необходимого значения min_doc_count. Это может привести к тому, что многие термины с высокой (глобальной) частотой будут отсутствовать в конечном результате, если в списки кандидатов попадут термины с низкой частотой, но высокой оценкой. Чтобы избежать этого, параметр shard_size можно увеличить, чтобы разрешить больше кандидатов на фрагментах. Однако это увеличивает потребление памяти и сетевой трафик.
shard_min_doc_count
Параметр shard_min_doc_count регулирует уверенность фрагмента в том, следует ли добавлять термин в список кандидатов или нет, относительно значения min_doc_count. Термины будут учитываться только в том случае, если их локальная частота на фрагменте в наборе выше, чем shard_min_doc_count. Если ваш словарь содержит много терминов с низкой частотой, и вы не заинтересованы в них (например, в ошибках написания), то вы можете установить параметр shard_min_doc_count для фильтрации кандидатов на уровне фрагмента, которые с достаточной вероятностью не достигнут необходимого значения min_doc_count даже после объединения локальных подсчётов. Параметр shard_min_doc_count по умолчанию установлен в значение 0 и не оказывает влияния, если его явно не установить.
Установка значения min_doc_count в значение 1 обычно не рекомендуется, так как это приводит к возврату терминов, представляющих собой опечатки или другие странные совпадения. Нахождение более одного экземпляра термина помогает подтвердить, что, хотя он всё ещё редок, термин не является результатом случайной ошибки. Значение по умолчанию 3 используется для обеспечения минимального уровня доказательств. Установка значения shard_min_doc_count слишком высоким приведёт к фильтрации значительного количества кандидатов на уровне фрагмента. Это значение следует установить гораздо ниже, чем min_doc_count/#shards.
Пользовательский контекст фонового фона
По умолчанию источником статистической информации о частотах фоновых терминов является весь индекс, и этот объём может быть сужен с помощью background_filter, чтобы сфокусироваться на значимых терминах в более узком контексте:
resp = client.search(
query={
"match": {
"city": "madrid"
}
},
aggs={
"tags": {
"significant_terms": {
"field": "tag",
"background_filter": {
"term": {
"text": "spain"
}
}
}
}
},
)
print(resp) response = client.search(
body: {
query: {
match: {
city: 'madrid'
}
},
aggregations: {
tags: {
significant_terms: {
field: 'tag',
background_filter: {
term: {
text: 'spain'
}
}
}
}
}
}
)
puts response const response = await client.search({
query: {
match: {
city: "madrid",
},
},
aggs: {
tags: {
significant_terms: {
field: "tag",
background_filter: {
term: {
text: "spain",
},
},
},
},
},
});
console.log(response); GET /_search
{
"query": {
"match": {
"city": "madrid"
}
},
"aggs": {
"tags": {
"significant_terms": {
"field": "tag",
"background_filter": {
"term": { "text": "spain" }
}
}
}
}
} Вышеприведённый фильтр поможет сфокусироваться на терминах, характерных для города Мадрид, а не на таких терминах, как «Испанский», которые необычны в глобальном контексте всего индекса, но распространены в подмножестве документов, содержащих слово «Испания».
Использование фильтров фонового контекста замедлит запрос, так как для определения частоты каждого термина необходимо отфильтровать его записи.
Фильтрация значений
Возможна (хотя и редко необходима) фильтрация значений, для которых будут созданы корзины. Это можно сделать с помощью параметров include и exclude, которые основаны на строке регулярного выражения или массивах точных терминов. Эта функциональность дублирует функции, описанные в документации по агрегации терминов.
Режим сбора
Для избежания проблем с памятью, агрегация significant_terms всегда вычисляет дочерние агрегации в режиме breadth_first. Описание различных режимов сбора можно найти в документации по агрегации терминов.
Указание выполнения
Существует несколько механизмов выполнения агрегации терминов:
- с использованием значений полей непосредственно для агрегации данных по корзинам (
map) - с использованием глобальных порядковых номеров поля и выделения одной корзины на глобальный порядковый номер (
global_ordinals)
Elasticsearch старается использовать разумные значения по умолчанию, поэтому, как правило, настройка не требуется.
global_ordinals — это параметр по умолчанию для поля keyword, он использует глобальные порядковые номера для динамического выделения корзин, так что потребление памяти линейно зависит от количества значений документов, входящих в объём агрегации.
map следует рассматривать только в случае, если очень мало документов соответствует запросу. В противном случае режим выполнения на основе порядковых номеров значительно быстрее. По умолчанию map используется только при выполнении агрегации на скриптах, поскольку у них нет порядковых номеров.
resp = client.search(
aggs={
"tags": {
"significant_terms": {
"field": "tags",
"execution_hint": "map"
}
}
},
)
print(resp) response = client.search(
body: {
aggregations: {
tags: {
significant_terms: {
field: 'tags',
execution_hint: 'map'
}
}
}
}
)
puts response const response = await client.search({
aggs: {
tags: {
significant_terms: {
field: "tags",
execution_hint: "map",
},
},
},
});
console.log(response); GET /_search
{
"aggs": {
"tags": {
"significant_terms": {
"field": "tags",
"execution_hint": "map"
}
}
}
} | возможные значения — |
Обратите внимание, что Elasticsearch проигнорирует это указание выполнения, если оно неприменимо.
© 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-significantterms-aggregation.html