Группировка результатов поиска с помощью StructArray
Используйте эту страницу для группировки результатов поиска на уровне элементов StructArray по родительскому объекту. Поиск на уровне элементов может возвращать несколько результатов из одного и того же объекта, если несколько элементов Struct соответствуют запросу. Группировка сворачивает эти результаты на уровне элементов, так что каждый родительский объект отображается не более одного раза.
На этой странице используется коллекция « tech_articles » из раздела «Создание поля StructArray». В коллекции имеется поле StructArray с именем « chunks ». Поле-вектор « chunks[emb] » индексировано для поиска на уровне элементов с использованием стандартной векторной метрики.
Как группировка применяется к StructArray
| Режим поиска | Поведение группировки | Поведение результатов |
|---|---|---|
| Поиск в EmbeddingList | Не поддерживается. | Не применимо. |
| Поиск на уровне элементов | Поддерживается путем группировки по первичному ключу. | Возвращается не более одного результата на каждую родительскую сущность. Метаданные на уровне элементов сохраняются, поэтому индекс или смещение выбранного элемента могут быть возвращены при предоставлении доступа через API или SDK. |
| Гибридный поиск | Поддерживается только в том случае, если все подзапросы нацелены на векторные поля на уровне элементов в рамках одного и того же поля StructArray. | Подзапросы на уровне элементов группируются по первичному ключу перед обработкой окончательного результата. |
Используйте группировку, если поиск на уровне элементов без группировки возвращает слишком много дубликатов родительских сущностей. Если вы хотите, чтобы каждый совпадающий элемент Struct рассматривался как отдельный результат, используйте базовый векторный поиск с StructArray без параметра ` group_by_field`.
Прежде чем начать
Перед запуском группированного поиска подготовьте коллекцию, данные и индексы.
| Требования | Подробности |
|---|---|
| Векторное подполе на уровне элементов | Используйте подполе вектора StructArray, например chunks[emb], индексированное с помощью обычной векторной метрики. |
| Обычный векторный запрос | Используйте вектор обычного запроса, а не EmbeddingList. |
| Группировка по первичному ключу | Используйте первичный ключ коллекции в виде group_by_field, например doc_id. |
| Отсутствие параметров диапазона | Не сочетайте поиск с группировкой с параметрами поиска по диапазону, такими как radius или range_filter. |
Информацию о настройке индекса см. в разделе «Поля StructArray индекса».
Выполнение группированного поиска на уровне элементов
В приведенном ниже примере сначала выполняется поиск по отдельным фрагментам, а затем найденные элементы группируются по первичному ключу родительского объекта.
from pymilvus import MilvusClient
client = MilvusClient(
uri="http://localhost:19530",
token="root:Milvus",
)
query_vector = [0.19, 0.24, 0.30, 0.37]
results = client.search(
collection_name="tech_articles",
data=[query_vector],
anns_field="chunks[emb]",
limit=5,
group_by_field="doc_id",
output_fields=[
"doc_id",
"title",
"chunks[text]",
"chunks[section]",
"chunks[page]",
"chunks[quality_score]",
],
)
for hits in results:
for hit in hits:
print(
"doc_id:", hit["id"],
"distance:", hit["distance"],
"offset:", hit.get("offset"),
"entity:", hit["entity"],
)
Без группировки один и тот же doc_id может появиться несколько раз, если запросу соответствуют несколько фрагментов. При использовании group_by_field="doc_id" каждая родительская сущность появляется не более одного раза. Группировка сохраняет метаданные на уровне элементов, поэтому сгруппированный результат по-прежнему может включать выбранный индекс или смещение элемента Struct, если API или SDK его предоставляют.
Добавление скалярных фильтров
Вы можете комбинировать поиск с группировкой со скалярной фильтрацией StructArray. Используйте « element_filter », когда скалярное условие должно ограничивать, какие элементы Struct участвуют в векторном поиске на уровне элементов.
filter_expr = (
'category == "search" && '
'element_filter(chunks, '
'$[section] == "index" && '
'$[quality_score] > 0.9)'
)
results = client.search(
collection_name="tech_articles",
data=[query_vector],
anns_field="chunks[emb]",
filter=filter_expr,
limit=5,
group_by_field="doc_id",
output_fields=[
"doc_id",
"title",
"category",
"chunks[text]",
"chunks[section]",
"chunks[quality_score]",
],
)
Предикат верхнего уровня выбирает кандидатов-сущностей. Предикат ` element_filter ` ограничивает векторный поиск на уровне элементов только соответствующими элементами Struct. Затем группировка сворачивает совпадающие элементы по первичному ключу.
Использование группировки в гибридном поиске
Гибридная группировка с StructArray является функцией на уровне элементов. Она поддерживается только в том случае, если все подпоиски нацелены на векторные поля на уровне элементов в рамках одного и того же поля StructArray. Не используйте запросы на уровне EmbeddingList в гибридном поиске по StructArray с группировкой.
В следующем примере предполагается, что поле StructArray « chunks » имеет два подполя векторного типа на уровне элементов: « chunks[emb] » и « chunks[code_emb] », и оба индексируются с помощью обычных векторных метрик.
from pymilvus import AnnSearchRequest, RRFRanker
index_chunk_req = AnnSearchRequest(
data=[query_vector],
anns_field="chunks[emb]",
limit=10,
expr='element_filter(chunks, $[section] == "index")',
)
code_chunk_req = AnnSearchRequest(
data=[code_query_vector],
anns_field="chunks[code_emb]",
limit=10,
expr='element_filter(chunks, $[has_code] == true)',
)
results = client.hybrid_search(
collection_name="tech_articles",
reqs=[index_chunk_req, code_chunk_req],
ranker=RRFRanker(),
limit=5,
group_by_field="doc_id",
output_fields=[
"doc_id",
"title",
"chunks[text]",
"chunks[section]",
],
)
В данном примере оба подзапроса нацелены на векторные поля на уровне элементов в рамках одного и того же поля StructArray — chunks. Гибридный поиск не поддерживает группировку на уровне элементов, если в нем смешаны обычные векторные поля, разные поля StructArray или запросы на уровне EmbeddingList.
Интерпретация сгруппированных результатов
| Элемент результата | Значение |
|---|---|
id | Первичный ключ сгруппированной родительской сущности. |
distance или оценка | Оценка или расстояние выбранного элемента Struct для данной родительской сущности. |
offset | Позиция выбранного элемента Struct с нулевой базой при возвращении. |
| Повторяющиеся первичные ключи | Не ожидаются при группировке по первичному ключу. |
limit | Применимо к сгруппированным результатам родительских сущностей. |
Ограничения
Поиск с группировкой применяется только к векторному поиску StructArray на уровне элементов. Поиск EmbeddingList и гибридный поиск на уровне EmbeddingList не поддерживают группировку.
Используйте первичный ключ в виде
group_by_field. Группировка на уровне элементов StructArray не является универсальной группировкой по произвольным скалярным полям.Не сочетайте поиск с группировкой с поиском по диапазону.
Не используйте запрос «
EmbeddingList» или метрику «MAX_SIM*» для группированного поиска.Гибридная группировка поддерживается только в том случае, если все подзапросы нацелены на векторные поля на уровне элементов в рамках одного и того же поля StructArray.
Гибридная группировка не поддерживается, если гибридный поиск сочетает обычное векторное поле, другое поле StructArray или запрос на уровне EmbeddingList.
Распространенные ошибки
Использование группировки с
chunks[emb_list_vector], которая предназначена для поиска по EmbeddingList.Группировка по скалярному полю, не являющемуся первичным ключом.
Группировка по нескольким полям. Группировка StructArray на уровне элементов поддерживает только группировку по первичному ключу.
Ожидание того, что сгруппированные результаты будут представлять каждый найденный элемент Struct. Группировка возвращает не более одного результата на каждую родительскую сущность.
Предположение, что группированный поиск на уровне элементов пересчитывает оценку
MAX_SIM*в стиле EmbeddingList. Группировка сворачивает совпадения на уровне элементов; она не изменяет модель оценки.Объединение
group_by_fieldсradiusилиrange_filter.
Следующие шаги
Чтобы сначала изучить поиск на уровне элементов без группировки, ознакомьтесь с разделом «Базовый векторный поиск с использованием StructArray».
Чтобы добавить скалярные фильтры к группированному поиску, ознакомьтесь с разделом «Фильтрованный поиск с StructArray».
Чтобы использовать границы оценки или расстояния вместо группировки, ознакомьтесь с разделом «Поиск по диапазону с StructArray».
Чтобы ознакомиться с ограничениями поиска с использованием StructArray, прочтите раздел «Ограничения StructArray».