Агрегация результатов поискаCompatible with Milvus 3.0.x
Когда покупатель ищет «черные кроссовки для ежедневных тренировок», поиск по методу ближайшего соседа (ANN) ранжирует товары по сходству векторов и возвращает плоский список Top-K. Результаты могут быть релевантными, но повторяющимися: в приведенном ниже примере четыре из первых шести результатов — товары бренда A, а бренды B и C появляются по одному разу.
Простой список не позволяет напрямую сформировать сводку, ориентированную на сегменты. Приложению может потребоваться сравнить бренды по количеству отобранных кандидатов или средней цене, проанализировать небольшое количество репрезентативных товаров от каждого бренда или сгруппировать результаты по нескольким уровням сегментов.
Агрегация результатов поиска группирует отобранные кандидаты ANN в сегменты на основе выбранных скалярных полей. В данном примере каждый бренд становится отдельным сегментом. Milvus может рассчитывать статистику для каждого сегмента, упорядочивать сегменты и привязывать к ним репрезентативные продукты. Приложение получает этот ответ, ориентированный на сегменты, через интерфейс « result.agg_buckets ».
Плоский набор результатов поиска кроссовок превращается в набор сопоставимых групп по брендам
Агрегация результатов поиска не выполняет точную агрегацию по всей коллекции. Наличие корзин, количество элементов, метрики, порядок и репрезентативные результаты зависят от кандидатов, отобранных на этапах ANN и группировки.
Как это работает
Кандидаты ANN, сгруппированные по ключам сегментов и возвращаемые с подсчётами, метриками и репрезентативными результатами
Извлечение кандидатов. Milvus запускает поиск с помощью ANN, чтобы найти сущности, наиболее близкие к вектору запроса. Затем на этапе группировки сохраняется ограниченное количество кандидатов для каждого полного составного ключа. Этот лимит кандидатов на ключ равен наибольшему значению
TopHits.sizeв любом месте дерева агрегации или1, если ни на одном уровне не задано значениеtop_hits.Построение корзин.
SearchAggregation.fieldsопределяет ключ корзины. Каждая уникальная комбинация значений полей создаёт отдельный ключ. На рисункеfields=["brand"]создаёт ключи корзин(Brand A),(Brand B)и(Brand C). Сохраненные кандидаты с одинаковым ключом относятся к одной корзине и вносят вклад в еёcount.SearchAggregation.sizeограничивает количество корзин, возвращаемых Milvus.Вычисление и возвращение результатов. Каждый возвращаемый бакет содержит свой ключ и количество сохраненных кандидатов. Milvus также может вычислять настроенные метрики, упорядочивать бакеты, возвращать репрезентативные сущности и создавать дочерние бакеты. Каждый
AggregationBucketвresult.agg_bucketsпредоставляетkey,count,metrics,hitsиsub_groups. Когда включена агрегация поиска, обычный список результатов поиска пуст.
На диаграмме TopHits.size=4 предоставляет бюджет кандидатов в размере четырех на каждый ключ, поэтому четыре сохраненных кандидата бренда A формируют count: 4. На готовой карте бренда A показаны только два из четырех возвращенных репрезентативных результатов, чтобы рисунок оставался компактным.
При использовании « sub_aggregation » Milvus повторяет шаги 2 и 3 внутри каждого родительского сегмента. Изменения в коэффициенте воспроизведения ANN или бюджете кандидатов на ключ могут повлиять на количество сегментов, метрики, порядок, результаты поиска и вложенные результаты.
Ограничения
Перед использованием агрегации поиска обратите внимание на следующие ограничения:
Вложенные агрегации: запрос может содержать одну корневую агрегацию «
SearchAggregation» и до трёх вложенных уровней «sub_aggregation», что в сумме даёт не более четырёх уровней. На всех уровнях для создания ключей корзин можно использовать не более 10 полей.Поля, используемые для создания ключей корзины: «
SearchAggregation.fields» поддерживает поля типа «Boolean», «integer», «VARCHAR» и «TIMESTAMPTZ». Не поддерживаются поля типа «FLOAT», «DOUBLE», «ARRAY», «JSON», «GEOMETRY», «TEXT», а также векторные и динамические поля.Поля метрики:
countпринимает"*"или любое не-JSON, нединамическое поле и пропускает значенияNULL, если указано поле.sumиavgпринимают целочисленные и поля с плавающей запятой.minиmaxдополнительно принимают строковые иTIMESTAMPTZполя.Поля сортировки Top Hits:
TopHits.sortдопускает сопоставимые поля типа «Boolean», «integer», «floating-point», «string» и «TIMESTAMPTZ», а также «_score». Не поддерживаются поля типа «ARRAY», «JSON», «GEOMETRY», векторные или динамические поля.Бюджет кандидатов: наибольшее значение
TopHits.sizeв любом месте дерева агрегации также является количеством кандидатов, сохраняемых на каждый полный составной ключ. Если ни на одном уровне не настроеноtop_hits, Milvus сохраняет одного кандидата на каждый ключ. Размер корзиныcountи метрики рассчитываются на основе этих сохраненных кандидатов, поэтому изменениеTopHits.sizeможет повлиять на них.Поля корзины, допускающие значение null: значение
NULLформирует собственный ключ корзины. Чтобы исключить корзину с нулевыми значениями, добавьте в запрос на поиск фильтр, напримерbrand is not null.Повторяющиеся поля: одно и то же поле не может фигурировать более чем в одном списке
SearchAggregation.fields. Например, если корневая агрегация используетfields=["category"], вложенная агрегацияsub_aggregationне может одновременно использоватьfields=["category"].Неподдерживаемые комбинации: агрегация поиска не может сочетаться с ненулевым значением параметра «
offset», итераторами поиска, гибридным поиском, выделением результатов или групповым поиском. Значение параметра «offset» верхнего уровня, равное «0», эквивалентно пропуску этого параметра. В запросах поиска REST v2 параметры «searchAggregation» и «ids» не могут указываться одновременно.Возвращаемые записи: по умолчанию Milvus отклоняет запрос на агрегацию результатов поиска, если рассчитанное максимальное количество записей в результатах превышает 10 000. Этот порог регулируется параметром
proxy.maxSearchAggregationResultEntries. Чтобы отключить эту проверку, установите значение конфигурации равным0или отрицательному числу.Milvus рассчитывает это максимальное количество следующим образом:
number of query vectors × product of the effective search_size at every aggregation level × largest TopHits.size at any levelДля этого вычисления на стороне сервера эффективным значением параметра «
search_size» на уровне является явно настроенное значение «search_size» или значение «size» для данного уровня, если параметр «search_size» опущен. API PyMilvus, используемое в данном руководстве, в настоящее время не предоставляет доступ к параметру «search_size», поэтому запросы PyMilvus используют значение «size» каждого уровня для этого вычисления. Используйте1для последнего множителя, если ни на одном уровне не настроеноTopHits. Например, один вектор запроса, 10 корневых корзин, пять дочерних корзин на каждую корневую корзину и два совпадения на каждую дочернюю корзину дают расчётный максимум:1 × 10 × 5 × 2 = 100
Используйте агрегацию поиска
Выберите пример в зависимости от того, что вы хотите достичь:
| Перейдите в | Описание | Ключевые настройки |
|---|---|---|
| Сравнение и сортировка корзин | Рассчитайте статистику по каждому сегменту для их сравнения, а затем отсортируйте полученные сегменты по метрикам, количествам или ключам. | fields, size, metrics, order |
| Показать репрезентативные результаты из каждого сегмента | Верните ограниченное количество объектов из каждого сегмента и отсортируйте эти объекты независимо друг от друга по скалярным полям или векторной оценке. | top_hits, TopHits.size, TopHits.sort |
| Группировка результатов на нескольких уровнях | Сгруппируйте результаты по уровням родительских и дочерних корзин для последовательного анализа нескольких измерений. | sub_aggregation |
В приведенных ниже примерах используется коллекция товаров с полями «бренд», «категория», «цвет», «цена» и «рейтинг». Все названия брендов, названия товаров, цены, рейтинги и результаты поиска являются синтетическими примерами данных. Разверните следующий раздел, чтобы создать коллекцию и определить общие переменные поиска.
from pymilvus import DataType, MilvusClient, SearchAggregation, TopHits
client = MilvusClient(
uri="http://localhost:19530",
token="root:Milvus",
)
collection_name = "product_search_aggregation"
if client.has_collection(collection_name):
client.drop_collection(collection_name)
schema = client.create_schema(auto_id=False, enable_dynamic_field=False)
schema.add_field("id", DataType.INT64, is_primary=True)
schema.add_field("embedding", DataType.FLOAT_VECTOR, dim=5)
schema.add_field("name", DataType.VARCHAR, max_length=200)
schema.add_field("brand", DataType.VARCHAR, max_length=100)
schema.add_field("category", DataType.VARCHAR, max_length=100)
schema.add_field("color", DataType.VARCHAR, max_length=50)
schema.add_field("price", DataType.DOUBLE)
schema.add_field("rating", DataType.DOUBLE)
schema.add_field("in_stock", DataType.BOOL)
index_params = client.prepare_index_params()
index_params.add_index(
field_name="embedding",
index_type="AUTOINDEX",
metric_type="COSINE",
)
client.create_collection(
collection_name=collection_name,
schema=schema,
index_params=index_params,
# Make preceding writes visible to searches from this client.
consistency_level="Session",
)
client.insert(
collection_name=collection_name,
data=[
{
"id": 1,
"embedding": [0.12, 0.42, 0.18, 0.66, 0.31],
"name": "Runner A1",
"brand": "Brand A",
"category": "running_shoes",
"color": "black",
"price": 129.99,
"rating": 4.7,
"in_stock": True,
},
{
"id": 2,
"embedding": [0.10, 0.39, 0.20, 0.61, 0.29],
"name": "Trail A2",
"brand": "Brand A",
"category": "running_shoes",
"color": "blue",
"price": 139.99,
"rating": 4.6,
"in_stock": True,
},
{
"id": 3,
"embedding": [0.14, 0.44, 0.19, 0.68, 0.33],
"name": "Runner B1",
"brand": "Brand B",
"category": "running_shoes",
"color": "white",
"price": 159.99,
"rating": 4.8,
"in_stock": True,
},
{
"id": 4,
"embedding": [0.16, 0.41, 0.22, 0.62, 0.30],
"name": "Runner C1",
"brand": "Brand C",
"category": "running_shoes",
"color": "red",
"price": 119.99,
"rating": 4.4,
"in_stock": False,
},
{
"id": 5,
"embedding": [0.48, 0.20, 0.59, 0.15, 0.71],
"name": "Jacket A1",
"brand": "Brand A",
"category": "jackets",
"color": "black",
"price": 99.99,
"rating": 4.5,
"in_stock": True,
},
{
"id": 6,
"embedding": [0.45, 0.18, 0.55, 0.17, 0.69],
"name": "Jacket B1",
"brand": "Brand B",
"category": "jackets",
"color": "blue",
"price": 89.99,
"rating": 4.3,
"in_stock": True,
},
{
"id": 7,
"embedding": [0.09, 0.38, 0.17, 0.60, 0.27],
"name": "Runner A3",
"brand": "Brand A",
"category": "running_shoes",
"color": "black",
"price": 159.99,
"rating": 4.8,
"in_stock": True,
},
{
"id": 8,
"embedding": [0.13, 0.43, 0.21, 0.65, 0.32],
"name": "Runner A4",
"brand": "Brand A",
"category": "running_shoes",
"color": "black",
"price": 149.99,
"rating": 4.9,
"in_stock": True,
},
],
)
client.load_collection(collection_name)
query_vector = [0.11, 0.40, 0.19, 0.64, 0.30]
search_params = {
"metric_type": "COSINE",
"params": {},
}
Приведенная выше настройка конфигурирует COSINE как для векторного индекса, так и для параметров поиска. Поэтому в последующих примерах используется {"_score": "desc"}, чтобы сначала отображать результаты с более высоким косинусным сходством. Для метрики расстояния, такой как L2, используйте {"_score": "asc"}.
Сравнение и сортировка корзин
Используйте этот шаблон, когда вам нужно сравнить группы найденных объектов с помощью вычисленных статистических показателей и контролировать порядок, в котором возвращаются корзины. В этом примере Milvus группирует найденные продукты по brand, вычисляет показатели цены для каждой корзины по брендам и сортирует корзины по средней цене.
Если ваша цель заключается лишь в повышении разнообразия результатов за счёт возврата одного или нескольких объектов на каждое значение поля, используйте вместо этого групповой поиск.
Следующая конфигурация создаёт до трёх групп по брендам, вычисляет показатели для каждой группы и сортирует группы по средней цене:
aggregation = SearchAggregation(
# Form one bucket for each distinct brand value.
fields=["brand"],
# Return up to three buckets at this aggregation level.
size=3,
# Calculate named metrics for every selected bucket.
metrics={
"product_count": {"count": "*"},
"avg_price": {"avg": "price"},
"min_price": {"min": "price"},
},
# Sort buckets by average price, highest first.
order=[
{"avg_price": "desc"},
# If average prices are equal, sort by bucket key in ascending order.
{"_key": "asc"},
],
)
Передайте объект в параметр search_aggregation метода MilvusClient.search():
result = client.search(
collection_name=collection_name,
data=[query_vector],
anns_field="embedding",
search_params=search_params,
output_fields=[
"name",
"brand",
"category",
"color",
"price",
"rating",
"in_stock",
],
search_aggregation=aggregation,
)
Когда установлен параметр ` search_aggregation `, PyMilvus не возвращает обычные совпадения сущностей в ` result[0]`. Вместо этого считывайте ответ по сегментам из ` result.agg_buckets[0] `. Параметр ` output_fields ` контролирует, какие скалярные поля появляются в каждом возвращаемом отображении ` AggregationHit.fields `; Milvus по-прежнему может использовать поля источника метрик и сортировки, которые не перечислены в ` output_fields`.
Следующий вывод был получен из вышеуказанного запроса и сериализован в формат JSON для удобства чтения. PyMilvus возвращает объекты AggregationBucket, а не JSON. Значение key всегда представляет собой упорядоченный список компонентов ключа, даже если fields содержит только одно поле. Это позволяет сохранить порядок полей для составных ключей.
[
{
"key": [
{
"field_id": 103,
"field_name": "brand",
"value": "Brand B"
}
],
"count": 1,
"metrics": {
"product_count": 1,
"avg_price": 159.99,
"min_price": 159.99
},
"hits": [],
"sub_groups": []
},
{
"key": [
{
"field_id": 103,
"field_name": "brand",
"value": "Brand A"
}
],
"count": 1,
"metrics": {
"product_count": 1,
"avg_price": 129.99,
"min_price": 129.99
},
"hits": [],
"sub_groups": []
},
{
"key": [
{
"field_id": 103,
"field_name": "brand",
"value": "Brand C"
}
],
"count": 1,
"metrics": {
"product_count": 1,
"avg_price": 119.99,
"min_price": 119.99
},
"hits": [],
"sub_groups": []
}
]
Для вектора с одним запросом, приведённого в данном руководстве, прочитайте возвращаемые корзины верхнего уровня из result.agg_buckets[0]. Каждая корзина предоставляет свои упорядоченные компоненты ключа, сохраненные кандидаты count, вычисленные значения metrics, репрезентативные значения hits и вложенные корзины в sub_groups.
Прочитайте конфигурацию следующим образом:
| Параметр | Что контролирует | В данном примере |
|---|---|---|
fields | Как Milvus создает ключи корзин | Создает один бакет для каждого уникального значения brand. |
size | Максимальное количество возвращаемых корзин | Возвращает до трёх корзин по брендам. |
metrics | Статистика, рассчитанная для каждого бакета | Рассчитывает количество товаров, среднюю цену и минимальную цену. |
order | Как Milvus сортирует возвращаемые сегменты | Сортировка производится по средней цене, а при равенстве значений используется ключ сегмента для определения порядка. |
Milvus игнорирует параметр « limit », если установлен параметр « search_aggregation ». Используйте значение корневого параметра « SearchAggregation.size » для управления количеством сегментов верхнего уровня.
При таких настройках Milvus возвращает сегменты «Brand B», «Brand A» и «Brand C» в порядке убывания значения avg_price. Критерий « _key » применяется только в том случае, если корзины имеют одинаковую среднюю цену. Поскольку в данной конфигурации не задан параметр « top_hits », список « hits » для каждой корзины пуст, а бюджет кандидата для каждого ключа равен « 1 ». Поэтому отображаемые значения количества и метрики описывают одного сохраненного кандидата на каждый бренд. Настройте параметр « top_hits » с более крупным значением « TopHits.size », если для агрегации требуется более широкое окно метрики для каждого ключа.
Каждая запись в файле SearchAggregation.metrics сопоставляет пользовательский псевдоним с {operation: source}:
| Источник | Поддерживаемые операции | Поведение |
|---|---|---|
Любое поле, не являющееся полемJSON и не являющееся динамическим полем | count | Подсчитывает сохраненные кандидаты, исходное поле которых не является полем типа NULL. |
| Поле целого или с плавающей запятой | sum, avg, min, max | Вычисляется по непустым сохраненным значениям. |
Поле типа «строка» или « TIMESTAMPTZ » | min, max | выбирает минимальное или максимальное непустое сохраненное значение. |
"*" | count | Подсчитывает количество всех сохраненных кандидатов в корзине. Результат соответствует bucket.count. |
_score | sum, avg, min, max | Агрегирует значения сходства или расстояния по ANN для сохраненных кандидатов. |
SearchAggregation.order Принимает следующие ключи:
| Ключ «Order» | Значение |
|---|---|
| Псевдоним метрики | Сортировка по значению, вычисленному в metrics на том же уровне агрегации, например avg_price. |
_count | Сортировка по количеству сохраненных кандидатов в каждом сегменте. |
_key | Сортировка по ключу корзины, а не по полю коллекции с именем « _key ». |
Каждая запись в « order » сопоставляет ключ значению « "asc" » или « "desc" ». Milvus оценивает несколько записей от первой до последней. Если опустить « order », Milvus сохраняет порядок обнаружения корзин из набора сохраненных кандидатов.
Чтобы отсортировать корзины по качеству совпадения векторов, сначала вычислите метрику на уровне корзины из _score, а затем используйте псевдоним метрики в order. Нельзя использовать _score напрямую в качестве ключа для упорядочивания корзин, поскольку каждая корзина может содержать несколько оценок сущностей. Например, при использовании COSINE или IP:
aggregation = SearchAggregation(
fields=["brand"],
size=3,
metrics={"max_score": {"max": "_score"}},
order=[{"max_score": "desc"}],
)
Используя L2, вычислите минимальное значение _score и отсортируйте псевдоним метрики по возрастанию, чтобы корзины с наименьшим расстоянием располагались первыми.
Чтобы создать составной ключ корзины, передайте несколько имен полей в одном списке:
aggregation = SearchAggregation(
# Combine brand and color to form a composite bucket key.
fields=["brand", "color"],
size=6,
)
Такая конфигурация может генерировать ключи, такие как (Brand A, black), (Brand A, blue) и (Brand B, white). Две сущности находятся в одном сегменте только в том случае, если оба значения совпадают. Milvus сохраняет порядок списка, поэтому brand является первым компонентом ключа, а color — вторым. Когда _key используется в order, Milvus сравнивает компоненты составного ключа в том же порядке. Передавайте несколько строк в одном плоском списке; вложенные списки не поддерживаются.
size=6 — это максимальное количество составных корзин, возвращаемых на данном уровне агрегации. Пример данных содержит пять различных комбинаций бренда и цвета, поэтому могут быть возвращены все пять. В пределе возвращаемых записей этот запрос вносит 1 query vector × 6 buckets × 1 = 6 настроенных записей результатов.
Наличие нескольких полей в одном списке SearchAggregation.fields создает составной ключ сегмента на данном уровне агрегации. Для создания иерархии сегментов «родитель-потомок» используйте вложенную агрегацию.
В приведенных ниже примерах переопределяется aggregation. Передайте обновленный объект в тот же параметр search_aggregation и повторно выполните вызов поиска.
Показать репрезентативные результаты из каждого сегмента
Включите репрезентативные сущности, если приложению необходимо отобразить реальные продукты из каждого сегмента. В этом примере Milvus возвращает до двух продуктов из каждого сегмента по бренду, отсортированных по рейтингу, а затем по векторному баллу.
Настройте параметр ` TopHits ` следующим образом:
aggregation = SearchAggregation(
fields=["brand"],
size=3,
# Return and sort representative entities for each selected bucket.
top_hits=TopHits(
# Return up to two entities per bucket.
size=2,
# Apply sort criteria in list order.
sort=[
{"rating": "desc"},
{"_score": "desc"},
],
),
)
Следующий сегмент «Бренд A» был извлечен из приведенного выше запроса и сериализован в формате JSON для удобства чтения.
{
"key": [
{
"field_id": 103,
"field_name": "brand",
"value": "Brand A"
}
],
"count": 2,
"metrics": {},
"hits": [
{
"pk": 1,
"score": 0.99976646900177,
"fields": {
"brand": "Brand A",
"category": "running_shoes",
"color": "black",
"in_stock": true,
"name": "Runner A1",
"price": 129.99,
"rating": 4.7
}
},
{
"pk": 2,
"score": 0.9997048377990723,
"fields": {
"brand": "Brand A",
"category": "running_shoes",
"color": "blue",
"in_stock": true,
"name": "Trail A2",
"price": 139.99,
"rating": 4.6
}
}
],
"sub_groups": []
}
| Параметр | Назначение |
|---|---|
top_hits | Необязательный. Настраивает репрезентативные сущности для данного уровня агрегации. Если параметр опущен, поле « bucket.hits » остается пустым, а бюджет кандидатов на ключ по умолчанию равен единице. |
TopHits.size | Возвращает до двух репрезентативных объектов из каждого выбранного сегмента и устанавливает бюджет кандидатов на ключ равным двум для всего дерева агрегации. |
TopHits.sort | Упорядочивает сущности внутри каждого сегмента с использованием перечисленных критериев. |
Настройте параметр « top_hits », если приложению требуются репрезентативные сущности или если для подсчётов и метрик необходимо более широкое окно кандидатов на ключ. Увеличение значения параметра « TopHits.size » повышает как бюджет кандидатов, так и максимальное количество возвращаемых записей при вычислении в разделе «Limits».
SearchAggregation.order сортирует корзины, в то время как « TopHits.sort » сортирует сохраненные сущности внутри каждой корзины. Порядок сортировки не влияет на то, какие кандидаты были сохранены для « count » и метрик. « TopHits.sort » принимает имена поддерживаемых сравниваемых скалярных полей и встроенное поле « _score », которое представляет сходство или расстояние по ANN. Milvus оценивает записи « sort » от первой до последней. В данном примере продукты сортируются по rating от наибольшего к наименьшему значению, а _score используется только в случае равенства двух оценок. Поскольку в настройках используется COSINE, убывающая сортировка по _score помещает более похожий продукт на первое место.
Поля, используемые в metrics или TopHits.sort, не обязательно должны фигурировать в output_fields. Milvus извлекает эти поля внутренне, но в отображение fields каждого возвращаемого результата включаются только поля, явно перечисленные в output_fields. Первичные ключи и векторные оценки остаются доступными через AggregationHit.pk и AggregationHit.score.
Каждый возвращаемый результат AggregationHit предоставляет свой первичный ключ в pk, векторный балл в score и запрашиваемые выходные поля в fields.
Группировка результатов на нескольких уровнях
Используйте вложенную агрегацию, когда вам нужен один уровень корзин внутри другого. В этом примере Milvus сначала создает корзины категорий, а затем создает корзины брендов внутри каждой категории.
Дочерняя агрегация получает только сущности, назначенные её родительскому сегменту. Параметр fields управляет ключом сегмента на каждом уровне агрегации, а параметр sub_aggregation формирует иерархию «родитель-дочерний».
Приведенная ниже конфигурация создает корзину категории с ключом (running_shoes). Внутри этой родительской корзины дочерняя агрегация создает отдельные корзины брендов с такими ключами, как (Brand A), (Brand B) и (Brand C).
Parent bucket key:
(running_shoes)
Child bucket keys:
├── (Brand A)
├── (Brand B)
└── (Brand C)
На каждом уровне можно независимо использовать несколько полей. Например, использование fields=["brand", "color"] в дочерней агрегации приведет к созданию составных дочерних ключей, таких как (Brand A, black).
Следующая конфигурация реализует эту иерархию:
aggregation = SearchAggregation(
fields=["category"],
size=2,
metrics={
"product_count": {"count": "*"},
"avg_price": {"avg": "price"},
},
order=[{"product_count": "desc"}],
# For each category bucket, group only its entities by brand.
sub_aggregation=SearchAggregation(
fields=["brand"],
size=3,
metrics={
"brand_count": {"count": "*"},
"avg_rating": {"avg": "rating"},
},
order=[{"avg_rating": "desc"}],
top_hits=TopHits(
size=2,
sort=[{"rating": "desc"}],
),
),
)
В приведённом ниже сериализованном отрывке показан родительский бакет running_shoes и его дочерний бакет «Brand B». Дочерние бакеты «Brand A» и «Brand C» опущены для краткости.
{
"key": [
{
"field_id": 104,
"field_name": "category",
"value": "running_shoes"
}
],
"count": 4,
"metrics": {
"avg_price": 137.49,
"product_count": 4
},
"hits": [],
"sub_groups": [
{
"key": [
{
"field_id": 103,
"field_name": "brand",
"value": "Brand B"
}
],
"count": 1,
"metrics": {
"avg_rating": 4.8,
"brand_count": 1
},
"hits": [
{
"pk": 3,
"score": 0.9994542598724365,
"fields": {
"brand": "Brand B",
"category": "running_shoes",
"color": "white",
"in_stock": true,
"name": "Runner B1",
"price": 159.99,
"rating": 4.8
}
}
],
"sub_groups": []
}
]
}
Отображаемый результат представляет путь к корзине (running_shoes) → (Brand B), а не отдельный составной ключ корзины (running_shoes, Brand B).
Сначала Milvus выбирает до двух корзин категорий, упорядоченных по product_count. Затем он независимо запускает запрос sub_aggregation в каждой выбранной категории и возвращает до трёх корзин брендов, упорядоченных по avg_rating.
В приведённом выше выводе:
- корневой блок «
running_shoes» содержит четыре отобранных кандидата по своим дочерним составным ключам. Его «metrics» содержат значения «avg_price» и «product_count» корневого уровня. - Список
sub_groupsкорневого сегмента содержит дочерние сегменты брендов. Отображаемый сегмент бренда B содержит один сохраненный кандидат и собственные значенияavg_ratingиbrand_count. - Список
hitsкорневого корзины пуст, поскольку для корневой агрегации не настроено значениеtop_hits. Дочерний корзина бренда B содержит репрезентативное совпадение, поскольку значениеtop_hitsнастроено вsub_aggregation.
Часто задаваемые вопросы
Насколько точны подсчёты и метрики корзин?
Агрегация поиска суммирует сохраненные кандидаты ANN. Она не выполняет агрегацию по всей коллекции.
Сохранение кандидатов проходит два этапа аппроксимации. Поиск ANN может пропустить релевантные объекты коллекции, а на этапе группировки сохраняется не более TopHits.size кандидатов для каждого полного составного ключа. Если ни на одном уровне не настроено top_hits, это ограничение на ключ составляет один.
Например, предположим, что коллекция содержит 5 000 продуктов бренда A, и многие из них релевантны векторному запросу. Если при агрегации используется параметр ` TopHits(size=4)`, корзина бренда A может сохранить не более четырёх кандидатов для полного составного ключа. Параметры ` count ` и метрики описывают именно эти сохраненные кандидаты, а не все релевантные продукты бренда A и не все 5 000 объектов коллекции.
Приближенность имеет наибольшее значение, когда в агрегации « order » используется псевдоним метрики. Изменения в полноте поиска могут изменить значения метрик и, следовательно, повлиять на то, какие корзины попадают в « SearchAggregation.size ». Вложенная агрегация может усилить этот эффект, поскольку каждый дочерний уровень работает с сущностями, доступными в своей родительской корзине.
Если вам нужны точные статистические данные по каждому соответствующему объекту, используйте рабочий процесс агрегации точных запросов вместо агрегации поиска.
Чем агрегация поиска отличается от группированного поиска?
Выбор следует делать исходя из основной формы результатов приложения:
| Основная потребность | Рекомендуется | Результат для использования |
|---|---|---|
| Возвращает стандартный ранжированный список сущностей с меньшим количеством повторяющихся значений в поле группировки | Групповой поиск | Результаты плоского поиска для каждого вектора запроса |
| Просмотр или сравнение групп в виде корзин с ключами, подсчётами, метриками, упорядочением, репрезентативными результатами или дочерними корзинами | Агрегация результатов поиска | AggregationBucket объекты в result.agg_buckets |
Даже если в настройках агрегации результатов поиска задано « top_hits », основным ответом по-прежнему остаётся дерево корзин. Групповой поиск по-прежнему полезен, когда приложение уже обрабатывает обычные результаты поиска и в первую очередь нуждается в разнообразии результатов.
Эти API являются взаимоисключающими. PyMilvus генерирует исключение « ParamError », если в одном запросе сочетаются « search_aggregation » с « group_by_field » или « group_by_fields ».