Агрегирование значимых текстовых фрагментов
Агрегирование, возвращающее интересные или необычные вхождения свободных текстовых терминов в наборе. Оно похоже на агрегирование значимых терминов, но отличается:
- Оно специально разработано для использования с полями типа
text - Оно не требует данных полей или doc-значений
- Оно повторно анализирует текстовое содержимое в режиме реального времени, что позволяет фильтровать дублированные фрагменты шумного текста, которые иначе могут исказить статистику.
Повторный анализ больших наборов результатов потребует много времени и памяти. Рекомендуется использовать агрегирование `significant_text` в качестве дочернего агрегирования по выборке или разнородной выборке для ограничения анализа небольшим набором документов с наилучшим соответствием, например, 200. Это обычно улучшит скорость, использование памяти и качество результатов.
Примеры использования:
- Предложение "H5N1" при поиске пользователей по запросу "птичий грипп", чтобы расширить запросы
- Предложение ключевых слов, относящихся к символу биржевого тикера $ATI, для использования в автоматическом классификаторе новостей
В этих случаях выбираемые слова не просто самые популярные термины в результатах. Самые популярные слова, как правило, довольно скучны (и, из, о, мы, я, они …). Значимые слова — это слова, которые претерпели значительные изменения в популярности, измеренные между передним и задним наборами. Если термин «H5N1» существует только в 5 документах в индексе из 10 миллионов документов, а также встречается в 4 из 100 документов, составляющих результаты поиска пользователя, это значимо и, вероятно, очень важно для их поиска. 5/10 000 000 против 4/100 — это большая разница в частоте.
Базовое использование
В типичном случае передний набор, представляющий интерес, — это выборка из лучших результатов поиска по запросу, а задний набор, используемый для статистического сравнения, — это индекс или индексы, из которых были собраны результаты.
Пример:
GET news/_search
{
"query": {
"match": { "content": "Bird flu" }
},
"aggregations": {
"my_sample": {
"sampler": {
"shard_size": 100
},
"aggregations": {
"keywords": {
"significant_text": { "field": "content" }
}
}
}
}
} Ответ:
{
"took": 9,
"timed_out": false,
"_shards": ...,
"hits": ...,
"aggregations" : {
"my_sample": {
"doc_count": 100,
"keywords" : {
"doc_count": 100,
"buckets" : [
{
"key": "h5n1",
"doc_count": 4,
"score": 4.71235374214817,
"bg_count": 5
}
...
]
}
}
}
} Результаты показывают, что «h5n1» — это один из нескольких терминов, тесно связанных с птичьим гриппом. Он встречается всего 5 раз в нашем индексе в целом (см. bg_count), но 4 из них оказались в нашем образце из 100 документов по результатам поиска по запросу «птичий грипп». Это указывает на значимое слово, которое пользователь потенциально может добавить в свой поиск.
Обработка шумных данных с помощью filter_duplicate_text
Поля свободного текста часто содержат смесь исходного содержимого и механических копий текста (вырезка-вставка биографий, цепочки ответов по электронной почте, ретвиты, заголовки/футеры шаблонов, меню навигации по страницам, боковые панели с новостями, авторские права, стандартные оговорки, адреса).
В реальных данных эти дублируемые фрагменты текста часто появляются в результатах significant_text, если они не отфильтрованы. Фильтрация почти дублирующегося текста — сложная задача на этапе индексирования, но мы можем очистить данные в реальном времени во время запроса с помощью параметра filter_duplicate_text.
Сначала рассмотрим пример реальных данных без фильтрации, используя набор данных Signal media с миллионом новостных статей, охватывающих широкий спектр тем. Вот необработанные результаты значимого текста для поиска статей, упоминающих «elasticsearch»:
{
...
"aggregations": {
"sample": {
"doc_count": 35,
"keywords": {
"doc_count": 35,
"buckets": [
{
"key": "elasticsearch",
"doc_count": 35,
"score": 28570.428571428572,
"bg_count": 35
},
...
{
"key": "currensee",
"doc_count": 8,
"score": 6530.383673469388,
"bg_count": 8
},
...
{
"key": "pozmantier",
"doc_count": 4,
"score": 3265.191836734694,
"bg_count": 4
},
...
} В неочищенных документах появилось несколько странных терминов, которые, судя по всему, статистически связаны с появлением нашего поискового запроса «elasticsearch», например, «pozmantier». Мы можем углубиться в примеры этих документов, чтобы понять, почему «pozmantier» связан с этим запросом:
GET news/_search
{
"query": {
"simple_query_string": {
"query": "+elasticsearch +pozmantier"
}
},
"_source": [
"title",
"source"
],
"highlight": {
"fields": {
"content": {}
}
}
} Результаты показывают серию очень похожих новостных статей о жюри для ряда технологических проектов:
{
...
"hits": {
"hits": [
{
...
"_source": {
"source": "Presentation Master",
"title": "T.E.N. Announces Nominees for the 2015 ISE® North America Awards"
},
"highlight": {
"content": [
"City of San Diego Mike <em>Pozmantier</em>, Program Manager, Cyber Security Division, Department of",
" Janus, Janus <em>ElasticSearch</em> Security Visualization Engine "
]
}
},
{
...
"_source": {
"source": "RCL Advisors",
"title": "T.E.N. Announces Nominees for the 2015 ISE(R) North America Awards"
},
"highlight": {
"content": [
"Mike <em>Pozmantier</em>, Program Manager, Cyber Security Division, Department of Homeland Security S&T",
"Janus, Janus <em>ElasticSearch</em> Security Visualization Engine"
]
}
},
... Майк Позмантьер был одним из многих судей в жюри, и elasticsearch использовался в одном из многих оцениваемых проектов.
Как обычно, это длинное пресс-релиз было вырезано и вставлено различными новостными сайтами, и, следовательно, любые редкие имена, числа или опечатки в них становятся статистически связанными с нашим запросом.
К счастью, подобные документы, как правило, ранжируются аналогично, поэтому в качестве части анализа потока наиболее соответстующих документов, агрегация `significant_text` может применять фильтр для удаления последовательностей из 6 или более токенов, которые уже были встречены. Попробуем тот же запрос, но с включенным параметром filter_duplicate_text:
GET news/_search
{
"query": {
"match": {
"content": "elasticsearch"
}
},
"aggs": {
"sample": {
"sampler": {
"shard_size": 100
},
"aggs": {
"keywords": {
"significant_text": {
"field": "content",
"filter_duplicate_text": true
}
}
}
}
}
} Результаты анализа наших дедублицированных текстов, очевидно, более качественны для любого, кто знаком с Elastic Stack:
{
...
"aggregations": {
"sample": {
"doc_count": 35,
"keywords": {
"doc_count": 35,
"buckets": [
{
"key": "elasticsearch",
"doc_count": 22,
"score": 11288.001166180758,
"bg_count": 35
},
{
"key": "logstash",
"doc_count": 3,
"score": 1836.648979591837,
"bg_count": 4
},
{
"key": "kibana",
"doc_count": 3,
"score": 1469.3020408163263,
"bg_count": 5
}
]
}
}
}
} Г-н Позмантьер и другие одноразовые ассоциации с elasticsearch больше не появляются в результатах агрегации в результате операций копирования-вставки или других форм механического повторения.
Если ваш дублируемый или почти дублируемый контент можно определить с помощью индексированного поля с одним значением (возможно, хэш текста статьи title или поля original_press_release_url), то будет эффективнее использовать родительское агрегирование разнородной выборки для удаления этих документов из набора выборок на основе этого единственного ключа. Чем меньше дублируемого содержимого вы сможете подать на вход агрегации `significant_text`, тем лучше с точки зрения производительности.
Ограничения
Отсутствует поддержка дочерних агрегаций
Агрегация `significant_text` намеренно не поддерживает добавление дочерних агрегаций, потому что:
- Это приведет к высоким затратам памяти
- Это не является общеполезной функцией, и для тех, кому она нужна, существует обходной путь
Объем кандидатных терминов, как правило, очень высок, и они сильно сокращаются, прежде чем будут возвращены окончательные результаты. Поддержка дочерних агрегаций приведет к дополнительным издержкам и будет неэффективной. Клиенты всегда могут взять сильно сокращенный набор результатов из запроса significant_text и выполнить последующий запрос, используя агрегацию terms с клаузой include и дочерними агрегациями для дальнейшего анализа выбранных ключевых слов более эффективным способом.
Отсутствует поддержка вложенных объектов
В настоящее время агрегация `significant_text` также не может использоваться с текстовыми полями во вложенных объектах, потому что она работает с исходным JSON-документом. Это делает эту функцию неэффективной при сопоставлении вложенных документов из хранимого JSON, учитывая соответствующий идентификатор документа Lucene.
Приближенные подсчеты
Подсчеты того, сколько документов содержат термин, предоставленный в результатах, основаны на суммировании образцов, возвращаемых каждым фрагментом, и поэтому могут быть:
- низкими, если некоторые фрагменты не предоставили данные для данного термина в своем образце
- высокими при рассмотрении частоты фона, поскольку он может учитывать случаи, найденные в удаленных документах
Как и большинство проектных решений, это компромисс, в котором мы выбрали быструю производительность в ущерб некоторым (как правило, небольшим) неточностям. Тем не менее, параметры size и shard size, о которых говорится в следующем разделе, предоставляют инструменты для управления уровнями точности.
Параметры
Эвристики значимости
Эта агрегация поддерживает те же эвристики оценки (JLH, mutual_information, gnd, chi_square и т.д.), что и агрегация значимых терминов.
Размер и размер фрагмента
Параметр 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. Значение по умолчанию равно 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, чтобы сфокусироваться на значимых терминах в более узком контексте:
GET news/_search
{
"query": {
"match": {
"content": "madrid"
}
},
"aggs": {
"tags": {
"significant_text": {
"field": "content",
"background_filter": {
"term": { "content": "spain" }
}
}
}
}
} Вышеуказанный фильтр поможет сфокусироваться на терминах, характерных для города Мадрид, а не на раскрытии терминов, таких как «испанский», которые нетипичны для всего мирового контекста полного индекса, но распространены в подмножестве документов, содержащих слово «Испания».
Использование фильтров фона замедлит запрос, так как для определения частоты каждого термина необходимо отфильтровать его сведения о размещении.
Обработка соответствий источника и индекса
Обычно имя индексированного поля и имя исходного поля JSON, которое извлекается, совпадают. Однако с более сложными соответствиями полей, использующими функции, такие как copy_to, исходное поле(я) JSON и индексированное поле, по которому выполняется агрегация, могут отличаться. В этих случаях можно перечислить поля _source JSON, текст которых будет анализироваться, с помощью параметра source_fields:
GET news/_search
{
"query": {
"match": {
"custom_all": "elasticsearch"
}
},
"aggs": {
"tags": {
"significant_text": {
"field": "custom_all",
"source_fields": [ "content", "title" ]
}
}
}
} Фильтрация значений
Можно (хотя и редко необходимо) отфильтровать значения, для которых будут созданы корзины. Это можно сделать с помощью параметров include и exclude, которые основаны на строке регулярного выражения или массивах точных терминов. Эта функциональность повторяет функции, описанные в документации по агрегации терминов.
© 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-significanttext-aggregation.html