Агрегация Top hits
Метрический агрегатор top_hits отслеживает наиболее релевантный документ, подвергнутый агрегированию. Этот агрегатор предназначен для использования в качестве под-агрегатора, чтобы можно было агрегировать лучшие совпадающие документы в каждом бакете.
Не рекомендуется использовать top_hits в качестве агрегации верхнего уровня. Если вы хотите сгруппировать результаты поиска, используйте параметр collapse вместо этого.
Агрегатор top_hits эффективно используется для группировки наборов результатов по определенным полям с помощью агрегатора бакетов. Один или несколько агрегаторов бакетов определяют, по каким свойствам набор результатов разбивается на части.
Параметры
-
from— Смещение от первого результата, который вы хотите получить. -
size— Максимальное количество лучших совпадающих результатов, возвращаемых в каждом бакете. По умолчанию возвращаются три лучших совпадающих результата. -
sort— Порядок сортировки лучших совпадающих результатов. По умолчанию результаты сортируются по оценке основного запроса.
Поддерживаемые функции для каждого результата
Агрегация top_hits возвращает обычные результаты поиска, поэтому поддерживается множество функций для каждого результата:
Если вам только нужны docvalue_fields, size и sort, то Агрегация top metrics может быть более эффективным выбором, чем агрегация Top Hits.
Агрегация top_hits не поддерживает параметр rescore. Переоценка запроса применяется только к результатам поиска, а не к результатам агрегирования. Чтобы изменить оценки, используемые в агрегациях, используйте запрос function_score или script_score.
Пример
В следующем примере мы группируем продажи по типу и по каждому типу отображаем последнюю продажу. Для каждой продажи включаются только поля date и price.
POST /sales/_search?size=0
{
"aggs": {
"top_tags": {
"terms": {
"field": "type",
"size": 3
},
"aggs": {
"top_sales_hits": {
"top_hits": {
"sort": [
{
"date": {
"order": "desc"
}
}
],
"_source": {
"includes": [ "date", "price" ]
},
"size": 1
}
}
}
}
}
} Возможный ответ:
{
...
"aggregations": {
"top_tags": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "hat",
"doc_count": 3,
"top_sales_hits": {
"hits": {
"total" : {
"value": 3,
"relation": "eq"
},
"max_score": null,
"hits": [
{
"_index": "sales",
"_type": "_doc",
"_id": "AVnNBmauCQpcRyxw6ChK",
"_source": {
"date": "2015/03/01 00:00:00",
"price": 200
},
"sort": [
1425168000000
],
"_score": null
}
]
}
}
},
{
"key": "t-shirt",
"doc_count": 3,
"top_sales_hits": {
"hits": {
"total" : {
"value": 3,
"relation": "eq"
},
"max_score": null,
"hits": [
{
"_index": "sales",
"_type": "_doc",
"_id": "AVnNBmauCQpcRyxw6ChL",
"_source": {
"date": "2015/03/01 00:00:00",
"price": 175
},
"sort": [
1425168000000
],
"_score": null
}
]
}
}
},
{
"key": "bag",
"doc_count": 1,
"top_sales_hits": {
"hits": {
"total" : {
"value": 1,
"relation": "eq"
},
"max_score": null,
"hits": [
{
"_index": "sales",
"_type": "_doc",
"_id": "AVnNBmatCQpcRyxw6ChH",
"_source": {
"date": "2015/01/01 00:00:00",
"price": 150
},
"sort": [
1420070400000
],
"_score": null
}
]
}
}
}
]
}
}
} Пример сжатия полей
Сжатие полей или группировка результатов — это функция, которая логически группирует набор результатов в группы и для каждой группы возвращает лучшие документы. Порядок групп определяется релевантностью первого документа в группе. В Elasticsearch это можно реализовать с помощью агрегатора бакетов, который заключает агрегатор top_hits в качестве под-агрегатора.
В примере ниже мы ищем по проиндексированным веб-страницам. Для каждой веб-страницы мы храним тело страницы и домен, к которому относится веб-страница. Определяя агрегатор terms по полю domain, мы группируем набор результатов веб-страниц по домену. Затем агрегатор top_hits определяется как под-агрегатор, чтобы собирались лучшие совпадающие результаты в каждом бакете.
Также определен агрегатор max, который используется функцией сортировки агрегатора terms для возвращения бакетов в порядке релевантности наиболее релевантного документа в бакете.
POST /sales/_search
{
"query": {
"match": {
"body": "elections"
}
},
"aggs": {
"top_sites": {
"terms": {
"field": "domain",
"order": {
"top_hit": "desc"
}
},
"aggs": {
"top_tags_hits": {
"top_hits": {}
},
"top_hit" : {
"max": {
"script": {
"source": "_score"
}
}
}
}
}
}
} В настоящее время для обеспечения сортировки бакетов из агрегатора terms по оценке наиболее релевантной веб-страницы по домену необходим агрегатор max (или min). К сожалению, агрегатор top_hits пока не может использоваться в опции order агрегатора terms.
Поддержка top_hits в вложенном или обратном вложенном агрегаторе
Если агрегатор top_hits заключен в агрегатор nested или reverse_nested, то возвращаются вложенные результаты. Вложенные результаты — это, по сути, скрытые мини-документы, которые являются частью обычных документов, где в схеме был настроен тип поля вложенного типа. Агрегатор top_hits может отображать эти документы, если он заключен в агрегатор nested или reverse_nested. Подробнее о вложенных типах в сопоставлении типа вложенного поля.
Если тип вложенного поля настроен, один документ фактически индексируется как несколько документов Lucene, и они имеют один и тот же идентификатор. Для определения идентичности вложенного результата требуется больше, чем просто идентификатор, поэтому вложенные результаты также содержат свою вложенную идентификацию. Вложенная идентификация хранится в поле _nested в результате поиска и содержит поле массива и смещение в массиве, к которому относится вложенный результат. Смещение нулевое.
Посмотрим, как это работает на реальном примере. Рассмотрим следующую схему:
PUT /sales
{
"mappings": {
"properties": {
"tags": { "type": "keyword" },
"comments": {
"type": "nested",
"properties": {
"username": { "type": "keyword" },
"comment": { "type": "text" }
}
}
}
}
} |
|
И некоторые документы:
PUT /sales/_doc/1?refresh
{
"tags": [ "car", "auto" ],
"comments": [
{ "username": "baddriver007", "comment": "This car could have better brakes" },
{ "username": "dr_who", "comment": "Where's the autopilot? Can't find it" },
{ "username": "ilovemotorbikes", "comment": "This car has two extra wheels" }
]
} Теперь можно выполнить следующую агрегацию top_hits (вложенную в агрегацию nested):
POST /sales/_search
{
"query": {
"term": { "tags": "car" }
},
"aggs": {
"by_sale": {
"nested": {
"path": "comments"
},
"aggs": {
"by_user": {
"terms": {
"field": "comments.username",
"size": 1
},
"aggs": {
"by_nested": {
"top_hits": {}
}
}
}
}
}
}
} Извлеченный фрагмент ответа top hits с вложенным результатом, расположенным в первом элементе поля массива comments:
{
...
"aggregations": {
"by_sale": {
"by_user": {
"buckets": [
{
"key": "baddriver007",
"doc_count": 1,
"by_nested": {
"hits": {
"total" : {
"value": 1,
"relation": "eq"
},
"max_score": 0.3616575,
"hits": [
{
"_index": "sales",
"_type" : "_doc",
"_id": "1",
"_nested": {
"field": "comments",
"offset": 0
},
"_score": 0.3616575,
"_source": {
"comment": "This car could have better brakes",
"username": "baddriver007"
}
}
]
}
}
}
...
]
}
}
}
} | Имя поля массива, содержащего вложенный результат | |
| Позиция вложенного результата в содержащем массиве | |
| Источник вложенного результата |
Если запрашивается _source, то возвращается только часть источника вложенного объекта, а не весь источник документа. Также доступны сохраненные поля на уровне вложенного внутреннего объекта через агрегатор top_hits, заключённого в агрегатор nested или reverse_nested.
Только вложенные результаты будут содержать поле _nested в результате, у невложенных (обычных) результатов этого поля не будет.
Информация в _nested также может использоваться для обработки исходного источника в другом месте, если _source не включено.
Если в схеме определены несколько уровней вложенных типов объектов, информация _nested также может быть иерархической, чтобы выразить идентичность вложенных результатов, находящихся на глубине двух слоёв или больше.
В примере ниже вложенный результат расположен в первом элементе поля nested_grand_child_field, которое затем расположено во втором элементе поля nested_child_field:
...
"hits": {
"total" : {
"value": 2565,
"relation": "eq"
},
"max_score": 1,
"hits": [
{
"_index": "a",
"_type": "b",
"_id": "1",
"_score": 1,
"_nested" : {
"field" : "nested_child_field",
"offset" : 1,
"_nested" : {
"field" : "nested_grand_child_field",
"offset" : 0
}
}
"_source": ...
},
...
]
}
...
© 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-metrics-top-hits-aggregation.html