Raggruppamento dei risultati di ricerca con StructArray

Utilizzare questa pagina per raggruppare i risultati della ricerca a livello di elemento StructArray in base all'entità padre. La ricerca a livello di elemento può restituire più risultati provenienti dalla stessa entità quando diversi elementi Struct corrispondono alla query. Il raggruppamento raggruppa tali risultati a livello di elemento in modo che ogni entità padre appaia al massimo una volta.

Questa pagina utilizza la raccolta « tech_articles » descritta in «Creazione di un campo StructArray». La raccolta presenta un campo StructArray denominato « chunks ». Il sottocampo vettoriale « chunks[emb] » è indicizzato per la ricerca a livello di elemento con una metrica vettoriale regolare.

Come si applica il raggruppamento a StructArray

Modalità di ricercaComportamento del raggruppamentoComportamento dei risultati
Ricerca EmbeddingListNon supportato.Non applicabile.
Ricerca a livello di elementoSupportata tramite raggruppamento sulla chiave primaria.Restituisce al massimo un risultato per entità padre. I metadati a livello di elemento vengono conservati, pertanto l'indice o l'offset dell'elemento selezionato può essere restituito quando esposto dall'API o dall'SDK.
Ricerca ibridaSupportata solo quando tutte le sotto-ricerche hanno come obiettivo campi vettoriali a livello di elemento all'interno dello stesso campo StructArray.Le sotto-ricerche a livello di elemento vengono raggruppate in base alla chiave primaria prima della gestione del risultato finale.

Utilizzare il raggruppamento quando la ricerca a livello di elemento non raggruppata restituisce troppe entità padre duplicate. Se si desidera che ogni elemento Struct corrispondente venga considerato come un singolo risultato, utilizzare la ricerca vettoriale di base con StructArray senza l'opzione ` group_by_field`.

Prima di iniziare

Preparare la raccolta, i dati e gli indici prima di eseguire la ricerca con raggruppamento.

RequisitiDettagli
Sottocampo vettoriale a livello di elementoUtilizzare un sottocampo vettoriale StructArray, ad esempio chunks[emb], indicizzato con una metrica vettoriale regolare.
Query vettoriale regolareUtilizzare un vettore di query regolare, non un EmbeddingList.
Raggruppamento per chiave primariaUtilizzare la chiave primaria della collezione come group_by_field, ad esempio doc_id.
Nessun parametro di intervalloNon combinare la ricerca per raggruppamento con parametri di ricerca per intervallo come radius o range_filter.

Per la configurazione dell'indice, consultare Campi StructArray dell'indice.

L'esempio seguente effettua prima la ricerca nei singoli chunk, quindi raggruppa i risultati a livello di elemento in base alla chiave primaria dell'entità padre.

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"],
        )

Senza raggruppamento, lo stesso doc_id può apparire più volte se diversi chunk corrispondono alla query. Con group_by_field="doc_id", ogni entità padre appare al massimo una volta. Il raggruppamento preserva i metadati a livello di elemento, quindi il risultato raggruppato può comunque includere l’indice o l’offset dell’elemento Struct selezionato quando l’API o l’SDK lo espongono.

Aggiungere filtri scalari

È possibile combinare la ricerca con raggruppamento con il filtraggio scalare di StructArray. Utilizzare element_filter quando la condizione scalare deve limitare quali elementi Struct partecipano alla ricerca vettoriale a livello di elemento.

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]",
    ],
)

Il predicato di primo livello seleziona le entità candidate. Il predicato ` element_filter ` limita la ricerca vettoriale a livello di elemento agli elementi Struct corrispondenti. Il raggruppamento raggruppa quindi i risultati corrispondenti in base alla chiave primaria.

Il raggruppamento ibrido con StructArray è una funzionalità a livello di elemento. È supportato solo quando tutte le sotto-ricerche hanno come obiettivo campi vettoriali a livello di elemento all’interno dello stesso campo StructArray. Non utilizzare richieste a livello di EmbeddingList in una ricerca ibrida raggruppata su StructArray.

L'esempio seguente presuppone che il campo StructArray chunks abbia due sottocampi vettoriali a livello di elemento, chunks[emb] e chunks[code_emb], ed entrambi siano indicizzati con metriche vettoriali regolari.

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]",
    ],
)

In questo esempio, entrambe le sotto-richieste hanno come obiettivo campi vettoriali a livello di elemento all’interno dello stesso campo StructArray, chunks. Una ricerca ibrida non supporta il raggruppamento a livello di elemento se mescola campi vettoriali normali, campi StructArray diversi o richieste a livello di EmbeddingList.

Interpretazione dei risultati raggruppati

Elemento del risultatoSignificato
idChiave primaria dell’entità padre raggruppata.
distance o punteggioPunteggio o distanza dell'elemento Struct selezionato per quell'entità padre.
offsetPosizione a partire da zero dell’elemento Struct selezionato al momento della restituzione.
Chiavi primarie ripetuteNon previsto in caso di raggruppamento in base alla chiave primaria.
limitSi applica ai risultati raggruppati dell’entità padre.

Limitazioni

  • La ricerca con raggruppamento si applica solo alla ricerca vettoriale StructArray a livello di elemento. La ricerca EmbeddingList e la ricerca ibrida a livello di EmbeddingList non supportano il raggruppamento.

  • Utilizzare la chiave primaria come group_by_field. Il raggruppamento a livello di elemento StructArray non è un raggruppamento generico su campi scalari arbitrari.

  • Non combinare la ricerca con raggruppamento con la ricerca per intervallo.

  • Non utilizzare una query di tipo " EmbeddingList " o una metrica " MAX_SIM* " per la ricerca raggruppata.

  • Il raggruppamento ibrido è supportato solo quando tutte le sotto-ricerche hanno come obiettivo campi vettoriali a livello di elemento all’interno dello stesso campo StructArray.

  • Il raggruppamento ibrido non è supportato quando la ricerca ibrida combina un campo vettoriale normale, un campo StructArray diverso o una richiesta a livello di EmbeddingList.

Errori comuni

  • Utilizzo del raggruppamento con ` chunks[emb_list_vector]`, destinato alla ricerca EmbeddingList.

  • Raggruppamento in base a un campo scalare non chiave primaria.

  • Raggruppamento in base a più campi. Il raggruppamento a livello di elemento di StructArray supporta solo il raggruppamento in base alla chiave primaria.

  • Aspettarsi che i risultati raggruppati rappresentino ogni elemento Struct corrispondente. Il raggruppamento restituisce al massimo un risultato per entità padre.

  • Presumere che la ricerca raggruppata a livello di elemento ricalcoli un punteggio di tipo " MAX_SIM* " in stile EmbeddingList. Il raggruppamento comprime i risultati a livello di elemento; non modifica il modello di punteggio.

  • Combinazione dell’ group_by_field con radius o range_filter.

Prossimi passi

  1. Per imparare innanzitutto la ricerca a livello di elemento non raggruppata, leggi Ricerca vettoriale di base con StructArray.

  2. Per aggiungere filtri scalari alla ricerca raggruppata, leggi Ricerca filtrata con StructArray.

  3. Per utilizzare limiti di punteggio o di distanza al posto del raggruppamento, leggi Ricerca per intervallo con StructArray.

  4. Per verificare i limiti di ricerca di StructArray, leggi Limiti di StructArray.