Regroupement des résultats de recherche avec StructArray
Utilisez cette page pour regrouper les résultats de recherche au niveau des éléments StructArray par entité parente. La recherche au niveau des éléments peut renvoyer plusieurs résultats provenant de la même entité lorsque plusieurs éléments Struct correspondent à la requête. Le regroupement regroupe ces résultats au niveau des éléments afin que chaque entité parente n'apparaisse qu'une seule fois au maximum.
Cette page utilise la collection « tech_articles » issue de la section «Créer un champ StructArray». La collection comporte un champ StructArray nommé « chunks ». Le sous-champ vectoriel « chunks[emb] » est indexé pour la recherche au niveau des éléments à l’aide d’une métrique vectorielle standard.
Comment le regroupement s’applique à StructArray
| Mode de recherche | Comportement du regroupement | Comportement des résultats |
|---|---|---|
| Recherche dans EmbeddingList | Non pris en charge. | Sans objet. |
| Recherche au niveau des éléments | Prise en charge par regroupement sur la clé primaire. | Renvoie au maximum un résultat par entité parente. Les métadonnées au niveau des éléments sont conservées ; ainsi, l’index ou le décalage de l’élément sélectionné peut être renvoyé lorsqu’il est exposé par l’API ou le SDK. |
| Recherche hybride | Prise en charge uniquement lorsque toutes les sous-recherches ciblent des champs vectoriels au niveau des éléments sous le même champ StructArray. | Les sous-recherches au niveau des éléments sont regroupées par clé primaire avant le traitement final des résultats. |
Utilisez le regroupement lorsque la recherche au niveau des éléments non regroupée renvoie trop d’entités parentes en double. Si vous souhaitez que chaque élément Struct correspondant soit considéré comme un résultat individuel, utilisez la recherche vectorielle de base avec StructArray sans l’option « group_by_field ».
Avant de commencer
Préparez la collection, les données et les index avant d’exécuter une recherche avec regroupement.
| Conditions requises | Détails |
|---|---|
| Sous-champ vectoriel au niveau de l'élément | Utilisez un sous-champ vectoriel de type StructArray, tel que chunks[emb], indexé à l'aide d'une métrique vectorielle standard. |
| Requête vectorielle standard | Utilisez un vecteur de requête standard, et non un EmbeddingList. |
| Regroupement par clé primaire | Utilisez la clé primaire de la collection sous la forme d'un « group_by_field », par exemple doc_id. |
| Pas de paramètres de plage | Ne combinez pas la recherche par regroupement avec des paramètres de recherche par plage tels que radius ou range_filter. |
Pour la configuration de l’index, voir Champs StructArray de l’index.
Exécuter une recherche groupée au niveau des éléments
L’exemple suivant recherche d’abord les chunks individuels, puis regroupe les résultats au niveau des éléments en fonction de la clé primaire de l’entité parente.
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"],
)
Sans regroupement, le même doc_id peut apparaître plusieurs fois si plusieurs blocs correspondent à la requête. Avec group_by_field="doc_id", chaque entité parente n'apparaît qu'une seule fois au maximum. Le regroupement préserve les métadonnées au niveau des éléments ; ainsi, le résultat regroupé peut toujours inclure l'index ou le décalage de l'élément Struct sélectionné lorsque l'API ou le SDK l'expose.
Ajouter des filtres scalaires
Vous pouvez combiner la recherche par regroupement avec le filtrage scalaire StructArray. Utilisez ` element_filter ` lorsque la condition scalaire doit restreindre les éléments Struct participant à la recherche vectorielle au niveau des éléments.
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]",
],
)
Le prédicat de niveau supérieur sélectionne les entités candidates. Le prédicat « element_filter » restreint la recherche vectorielle au niveau des éléments aux éléments Struct correspondants. Le regroupement regroupe ensuite les résultats d’éléments correspondants en fonction de la clé primaire.
Utilisation du regroupement dans la recherche hybride
Le regroupement hybride avec StructArray est une fonctionnalité au niveau des éléments. Il n’est pris en charge que lorsque toutes les sous-recherches ciblent des champs vectoriels au niveau des éléments appartenant au même champ StructArray. N’utilisez pas de requêtes au niveau de la liste d’embeddings (EmbeddingList) dans une recherche hybride StructArray regroupée.
L’exemple suivant part du principe que le champ StructArray « chunks » comporte deux sous-champs vectoriels au niveau des éléments, « chunks[emb] » et « chunks[code_emb] », et que ces deux sous-champs sont indexés à l’aide de métriques vectorielles standard.
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]",
],
)
Dans cet exemple, les deux sous-requêtes ciblent des champs vectoriels au niveau des éléments appartenant au même champ StructArray, chunks. Une recherche hybride ne prend pas en charge le regroupement au niveau des éléments si elle mélange des champs vectoriels normaux, différents champs StructArray ou des requêtes au niveau de la liste d’embeddement (EmbeddingList).
Interpréter les résultats regroupés
| Élément de résultat | Signification |
|---|---|
id | Clé primaire de l’entité parente regroupée. |
distance ou score | Score ou distance de l'élément Struct sélectionné pour cette entité parente. |
offset | Position (à partir de zéro) de l’élément Struct sélectionné lors du renvoi. |
| Clés primaires répétées | Non attendues lors d’un regroupement par clé primaire. |
limit | S'applique aux résultats groupés de l'entité parente. |
Limitations
La recherche par regroupement s’applique uniquement à la recherche vectorielle StructArray au niveau des éléments. La recherche EmbeddingList et la recherche hybride au niveau EmbeddingList ne prennent pas en charge le regroupement.
Utilisez la clé primaire comme «
group_by_field». Le regroupement au niveau des éléments StructArray n'est pas un regroupement polyvalent sur des champs scalaires arbitraires.Ne combinez pas la recherche avec regroupement et la recherche par plage.
N’utilisez pas de requête «
EmbeddingList» ni de métrique «MAX_SIM*» pour la recherche groupée.Le regroupement hybride n’est pris en charge que lorsque toutes les sous-recherches ciblent des champs vectoriels au niveau des éléments appartenant au même champ StructArray.
Le regroupement hybride n’est pas pris en charge lorsque la recherche hybride mélange un champ vectoriel normal, un autre champ StructArray ou une requête au niveau EmbeddingList.
Erreurs courantes
Utilisation du regroupement avec `
chunks[emb_list_vector]`, qui est destiné à la recherche EmbeddingList.Regroupement par un champ scalaire autre que la clé primaire.
Regroupement selon plusieurs champs. Le regroupement StructArray au niveau des éléments ne prend en charge que le regroupement par clé primaire.
S'attendre à ce que les résultats regroupés représentent chaque élément Struct correspondant. Le regroupement renvoie au maximum un résultat par entité parente.
Supposer que la recherche groupée au niveau des éléments recalcule un score de type «
MAX_SIM*» de type EmbeddingList. Le regroupement regroupe les résultats au niveau des éléments ; il ne modifie pas le modèle de notation.Combinaison de l’
group_by_fieldavecradiusourange_filter.
Étapes suivantes
Pour vous familiariser d’abord avec la recherche au niveau des éléments non regroupés, consultez la section « Recherche vectorielle de base avec StructArray ».
Pour ajouter des filtres scalaires à la recherche groupée, consultez la section « Recherche filtrée avec StructArray ».
Pour utiliser des limites de score ou de distance à la place du regroupement, consultez la section « Recherche par plage avec StructArray ».
Pour connaître les limites de la recherche avec StructArray, consultez la section « Limites de StructArray ».