Агрегация diversified sampler
Подобно агрегации sampler, это агрегация фильтрации, используемая для ограничения обработки любых вложенных агрегаций до выборки лучших документов по оценке. Агрегация diversified_sampler добавляет возможность ограничить количество совпадений, которые разделяют общее значение, например, "автор".
Любой хороший исследователь рынка скажет вам, что при работе с выборками данных важно, чтобы выборка представляла здоровое разнообразие мнений, а не была искажена каким-либо одним голосом. То же самое относится к агрегациям и выборке. Настройки diversifying могут помочь устранить предвзятость в ваших данных (перенаселенный регион, резкий скачок на временной шкале или чрезмерно активный спаммер форума).
Примеры использования:
- Уточнение фокуса аналитики на совпадениях с высокой релевантностью, а не потенциально очень длинном хвосте совпадений низкого качества
- Устранение предвзятости в аналитике, гарантируя справедливое представление контента из разных источников
- Сокращение эксплуатационных расходов агрегаций, которые могут давать полезные результаты, используя только выборки, например,
significant_terms
Настройка field используется для предоставления значений, используемых для исключения дубликатов, а настройка max_docs_per_value контролирует максимальное количество документов, собранных на каждом фрагменте, которые разделяют общее значение. Значение по умолчанию для max_docs_per_value равно 1.
Агрегация выведет ошибку, если field создаст несколько значений для одного документа (исключение дубликатов с использованием многозначных полей не поддерживается из-за проблем с производительностью).
Пример:
Мы можем захотеть увидеть, какие теги сильно связаны с #elasticsearch на форуме StackOverflow, но игнорируя влияние некоторых активных пользователей, которые имеют тенденцию неправильно писать #Kibana как #Cabana.
resp = client.search(
index="stackoverflow",
size="0",
query={
"query_string": {
"query": "tags:elasticsearch"
}
},
aggs={
"my_unbiased_sample": {
"diversified_sampler": {
"shard_size": 200,
"field": "author"
},
"aggs": {
"keywords": {
"significant_terms": {
"field": "tags",
"exclude": [
"elasticsearch"
]
}
}
}
}
},
)
print(resp) response = client.search(
index: 'stackoverflow',
size: 0,
body: {
query: {
query_string: {
query: 'tags:elasticsearch'
}
},
aggregations: {
my_unbiased_sample: {
diversified_sampler: {
shard_size: 200,
field: 'author'
},
aggregations: {
keywords: {
significant_terms: {
field: 'tags',
exclude: [
'elasticsearch'
]
}
}
}
}
}
}
)
puts response const response = await client.search({
index: "stackoverflow",
size: 0,
query: {
query_string: {
query: "tags:elasticsearch",
},
},
aggs: {
my_unbiased_sample: {
diversified_sampler: {
shard_size: 200,
field: "author",
},
aggs: {
keywords: {
significant_terms: {
field: "tags",
exclude: ["elasticsearch"],
},
},
},
},
},
});
console.log(response); POST /stackoverflow/_search?size=0
{
"query": {
"query_string": {
"query": "tags:elasticsearch"
}
},
"aggs": {
"my_unbiased_sample": {
"diversified_sampler": {
"shard_size": 200,
"field": "author"
},
"aggs": {
"keywords": {
"significant_terms": {
"field": "tags",
"exclude": [ "elasticsearch" ]
}
}
}
}
}
} Ответ:
{
...
"aggregations": {
"my_unbiased_sample": {
"doc_count": 151,
"keywords": {
"doc_count": 151,
"bg_count": 650,
"buckets": [
{
"key": "kibana",
"doc_count": 150,
"score": 2.213,
"bg_count": 200
}
]
}
}
}
} | Всего было отобрано 151 документ. | |
| Результаты агрегации significant_terms не искажены странностями ни одного автора, потому что мы запросили не более одного поста от одного автора в нашей выборке. |
Пример с использованием сценария
В этом сценарии мы можем захотеть провести диверсификацию по сочетанию значений полей. Мы можем использовать потоковое поле, чтобы создать хэш из нескольких значений в поле тегов, чтобы убедиться, что наша выборка не состоит из одних и тех же повторяющихся комбинаций тегов.
resp = client.search(
index="stackoverflow",
size="0",
query={
"query_string": {
"query": "tags:kibana"
}
},
runtime_mappings={
"tags.hash": {
"type": "long",
"script": "emit(doc['tags'].hashCode())"
}
},
aggs={
"my_unbiased_sample": {
"diversified_sampler": {
"shard_size": 200,
"max_docs_per_value": 3,
"field": "tags.hash"
},
"aggs": {
"keywords": {
"significant_terms": {
"field": "tags",
"exclude": [
"kibana"
]
}
}
}
}
},
)
print(resp) response = client.search(
index: 'stackoverflow',
size: 0,
body: {
query: {
query_string: {
query: 'tags:kibana'
}
},
runtime_mappings: {
'tags.hash' => {
type: 'long',
script: "emit(doc['tags'].hashCode())"
}
},
aggregations: {
my_unbiased_sample: {
diversified_sampler: {
shard_size: 200,
max_docs_per_value: 3,
field: 'tags.hash'
},
aggregations: {
keywords: {
significant_terms: {
field: 'tags',
exclude: [
'kibana'
]
}
}
}
}
}
}
)
puts response const response = await client.search({
index: "stackoverflow",
size: 0,
query: {
query_string: {
query: "tags:kibana",
},
},
runtime_mappings: {
"tags.hash": {
type: "long",
script: "emit(doc['tags'].hashCode())",
},
},
aggs: {
my_unbiased_sample: {
diversified_sampler: {
shard_size: 200,
max_docs_per_value: 3,
field: "tags.hash",
},
aggs: {
keywords: {
significant_terms: {
field: "tags",
exclude: ["kibana"],
},
},
},
},
},
});
console.log(response); POST /stackoverflow/_search?size=0
{
"query": {
"query_string": {
"query": "tags:kibana"
}
},
"runtime_mappings": {
"tags.hash": {
"type": "long",
"script": "emit(doc['tags'].hashCode())"
}
},
"aggs": {
"my_unbiased_sample": {
"diversified_sampler": {
"shard_size": 200,
"max_docs_per_value": 3,
"field": "tags.hash"
},
"aggs": {
"keywords": {
"significant_terms": {
"field": "tags",
"exclude": [ "kibana" ]
}
}
}
}
}
} Ответ:
{
...
"aggregations": {
"my_unbiased_sample": {
"doc_count": 6,
"keywords": {
"doc_count": 6,
"bg_count": 650,
"buckets": [
{
"key": "logstash",
"doc_count": 3,
"score": 2.213,
"bg_count": 50
},
{
"key": "elasticsearch",
"doc_count": 3,
"score": 1.34,
"bg_count": 200
}
]
}
}
}
} shard_size
Параметр shard_size ограничивает количество лучших документов, собранных в выборке, обрабатываемой на каждом фрагменте. Значение по умолчанию равно 100.
max_docs_per_value
max_docs_per_value — это необязательный параметр, который ограничивает количество документов, разрешенных для каждого выбранного значения исключения дубликатов. Значение по умолчанию равно "1".
execution_hint
Необязательная настройка execution_hint может повлиять на управление значениями, используемыми для исключения дубликатов. Каждый вариант будет хранить до shard_size значений в памяти во время выполнения исключения дубликатов, но тип хранимых значений можно контролировать следующим образом:
- непосредственно хранить значения поля (
map) - хранить порядковые номера поля, как определено индексом Lucene (
global_ordinals) - хранить хэши значений поля — с потенциальными коллизиями хэшей (
bytes_hash)
Значение по умолчанию — использовать global_ordinals, если эта информация доступна из индекса Lucene, и переходить к map, если нет. Настройка bytes_hash может быть быстрее в некоторых случаях, но вводит возможность ложных срабатываний в логике исключения дубликатов из-за возможности коллизий хэшей. Обратите внимание, что Elasticsearch проигнорирует выбранный executio hint, если он не применим, и что нет гарантии обратной совместимости для этих подсказок.
Ограничения
Не может быть вложена в агрегации breadth_first
В качестве агрегации, основанной на качестве, агрегация diversified_sampler должна иметь доступ к оценке релевантности, полученной для каждого документа. Поэтому она не может быть вложена в агрегацию terms, у которой режим collect_mode переключен из режима по умолчанию depth_first в режим breadth_first, так как это отбрасывает оценки. В этой ситуации будет выведена ошибка.
Ограниченная логика исключения дубликатов.
Логика исключения дубликатов применяется только на уровне фрагмента, поэтому не будет применяться между фрагментами.
Нет специализированного синтаксиса для гео/датовых полей
В настоящее время синтаксис определения значений диверсификации определяется выбором field или script — нет добавления синтаксического сахара для выражения гео- или временных единиц, таких как "7d" (7 дней). Эта поддержка может быть добавлена в будущих версиях, и пользователям в настоящее время придется создавать такие значения с помощью скрипта.
© 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-diversified-sampler-aggregation.html