Aggregazione dei risultati di ricercaCompatible with Milvus 3.0.x

Quando un acquirente cerca "scarpe da corsa nere per l'allenamento quotidiano", la ricerca "Approssimazione del vicino più prossimo" (ANN) classifica i prodotti in base alla somiglianza vettoriale e restituisce un elenco piatto Top-K. I risultati possono essere pertinenti ma ripetitivi: nell'esempio riportato di seguito, quattro dei primi sei risultati sono prodotti del Marchio A, mentre il Marchio B e il Marchio C compaiono una volta ciascuno.

Un elenco piatto non può fornire direttamente un riepilogo orientato ai bucket. Un’applicazione potrebbe dover confrontare i marchi in base al numero di candidati selezionati o al prezzo medio, esaminare un numero ridotto di prodotti rappresentativi di ciascun marchio oppure organizzare i risultati in più livelli di bucket.

L’aggregazione della ricerca organizza i candidati ANN selezionati in bucket in base a campi scalari selezionati. In questo esempio, ogni marchio diventa un bucket separato. Milvus può calcolare le statistiche per ciascun bucket, ordinare i bucket e associarvi prodotti rappresentativi. L’applicazione utilizza questa risposta “bucket-first” tramite result.agg_buckets.

A flat running-shoe search result becomes a set of comparable brand buckets Un risultato di ricerca piatto relativo alle scarpe da corsa diventa un insieme di bucket di marchi comparabili

L’aggregazione della ricerca non esegue un’aggregazione esatta dell’intera collezione. L’esistenza dei bucket, i conteggi, le metriche, l’ordinamento e i risultati rappresentativi dipendono dai candidati selezionati dalle fasi della rete neurale artificiale (ANN) e di raggruppamento.

Come funziona

ANN candidates grouped by bucket keys and returned with counts, metrics, and representative hits Candidati ANN raggruppati in base alle chiavi dei bucket e restituiti con conteggi, metriche e risultati rappresentativi

  1. Recupero dei candidati. Milvus esegue una ricerca ANN per individuare le entità più vicine al vettore di query. La fase di raggruppamento trattiene quindi un numero limitato di candidati per ciascuna chiave composita completa. Questo limite di candidati per chiave corrisponde al valore più grande di TopHits.size in qualsiasi punto dell’albero di aggregazione, oppure a 1 quando nessun livello configura top_hits.

  2. Creazione dei bucket. SearchAggregation.fields definisce la chiave del bucket. Ogni combinazione univoca di valori dei campi crea una chiave separata. Nella figura, fields=["brand"] crea le chiavi dei bucket (Brand A), (Brand B) e (Brand C). I candidati conservati con la stessa chiave appartengono allo stesso bucket e contribuiscono al suo count. SearchAggregation.size limita il numero di bucket restituiti da Milvus.

  3. Calcolo e restituzione dei risultati. Ogni bucket restituito contiene la propria chiave e il conteggio dei candidati conservati. Milvus può anche calcolare le metriche configurate, ordinare i bucket, restituire entità rappresentative e creare bucket secondari. Ogni AggregationBucket in result.agg_buckets espone key, count, metrics, hits e sub_groups. Quando l’aggregazione di ricerca è abilitata, il normale elenco dei risultati di ricerca è vuoto.

Nel diagramma, TopHits.size=4 fornisce un budget di candidati per chiave pari a quattro, quindi i quattro candidati del Marchio A conservati generano count: 4. La scheda completa del Marchio A mostra solo due dei quattro risultati rappresentativi restituiti per mantenere la figura compatta.

Con « sub_aggregation », Milvus ripete i passaggi 2 e 3 all’interno di ciascun bucket padre. Le variazioni nel recall della rete neurale artificiale (ANN) o nel budget di candidati per chiave possono modificare il numero di bucket, le metriche, l’ordinamento, i risultati e i risultati annidati.

Limiti

Prima di utilizzare l’aggregazione di ricerca, tenere presente i seguenti limiti:

  • Aggregazioni annidate: una richiesta può contenere un’aggregazione di ricerca radice ( SearchAggregation ) e fino a tre livelli di aggregazione di ricerca secondaria ( sub_aggregation ) annidati, per un massimo di quattro livelli in totale. A tutti i livelli, è possibile utilizzare al massimo 10 campi per creare le chiavi dei bucket.

  • Campi utilizzati per creare le chiavi di bucket: SearchAggregation.fields supporta campi booleani, interi, VARCHAR e TIMESTAMPTZ. Non supporta campi FLOAT, DOUBLE, ARRAY, JSON, GEOMETRY, TEXT, vettoriali o dinamici.

  • Campi metrici: count accetta "*" o qualsiasi campo nonJSON e non dinamico, e ignora i valori NULL quando viene specificato un campo. sum e avg accettano campi interi e in virgola mobile. min e max accettano inoltre campi stringa e TIMESTAMPTZ.

  • Campi di ordinamento dei Top Hits: TopHits.sort accetta campi comparabili di tipo booleano, intero, a virgola mobile, stringa e TIMESTAMPTZ, oltre a _score. Non supporta ARRAY, JSON, GEOMETRY, né campi vettoriali o dinamici.

  • Budget dei candidati: il valore più grande di ` TopHits.size ` in qualsiasi punto dell’albero di aggregazione corrisponde anche al numero di candidati conservati per ogni chiave composita completa. Se nessun livello configura ` top_hits`, Milvus conserva un candidato per ogni chiave. Il ` count ` del bucket e le metriche vengono calcolati a partire da questi candidati conservati, pertanto la modifica di ` TopHits.size ` può alterarli.

  • Campi del bucket nullabili: un valore NULL costituisce una chiave di bucket a sé stante. Per escludere il bucket nullo, aggiungere un filtro come brand is not null alla richiesta di ricerca.

  • Campi ripetuti: lo stesso campo non può comparire in più di un elenco di SearchAggregation.fields. Ad esempio, se l’aggregazione radice utilizza fields=["category"], un sub_aggregation annidato non può utilizzare anche fields=["category"].

  • Combinazioni non supportate: l’aggregazione di ricerca non può essere combinata con un ` offset` diverso da zero, iteratori di ricerca, ricerca ibrida, un evidenziatore o ricerca raggruppata. Un valore di primo livello ` offset ` pari a ` 0 ` equivale all’omissione del parametro. Nelle richieste di ricerca REST v2, ` searchAggregation ` e ` ids ` non possono essere specificati insieme.

  • Voci restituite: per impostazione predefinita, Milvus rifiuta una richiesta di aggregazione di ricerca quando il numero massimo calcolato di voci di risultato supera 10.000. Questa soglia è controllata da proxy.maxSearchAggregationResultEntries. Impostare il valore di configurazione su 0 o su un numero negativo per disabilitare questo controllo.

    Milvus calcola questo valore massimo come segue:

    number of query vectors × product of the effective search_size at every aggregation level × largest TopHits.size at any level

    Per questo calcolo lato server, il valore effettivo di ` search_size ` a un livello è il valore esplicitamente configurato in ` search_size`, oppure il valore di ` size ` di quel livello quando ` search_size ` è omesso. L’API PyMilvus utilizzata in questa guida attualmente non espone ` search_size`, pertanto le richieste PyMilvus utilizzano il valore di ` size ` di ciascun livello per questo calcolo. Utilizzare 1 come ultimo fattore quando nessun livello configura TopHits. Ad esempio, un vettore di query, 10 bucket radice, cinque bucket figli per ogni bucket radice e due hit per ogni bucket figlio producono un massimo calcolato pari a:

    1 × 10 × 5 × 2 = 100

Utilizza l’aggregazione di ricerca

Scegli un esempio in base a ciò che desideri ottenere:

Vai aDescrizioneImpostazioni chiave
Confronta e ordina i bucketCalcola le statistiche per ogni bucket per confrontarli, quindi ordina i bucket restituiti in base a metriche, conteggi o chiavi.fields, size, metrics, order
Mostra risultati rappresentativi da ciascun bucketRestituisci un numero limitato di entità da ciascun bucket e ordina tali entità in modo indipendente in base ai campi scalari o al punteggio vettoriale.top_hits, TopHits.size, TopHits.sort
Raggruppare i risultati su più livelliOrganizza i risultati in livelli di bucket padre e figlio per analizzare più dimensioni in sequenza.sub_aggregation

Gli esempi riportati di seguito utilizzano una raccolta di prodotti con campi relativi a marchio, categoria, colore, prezzo e valutazione. Tutti i nomi dei marchi, i nomi dei prodotti, i prezzi, le valutazioni e i risultati di ricerca sono dati di esempio sintetici. Espandi la sezione seguente per creare la raccolta e definire le variabili di ricerca condivise.

Configurazione della collezione di esempio

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": {},
}

La configurazione sopra riportata imposta COSINE sia per l’indice vettoriale che per i parametri di ricerca. Pertanto, gli esempi successivi utilizzano {"_score": "desc"} per posizionare per prime le somiglianze coseno più elevate. Per una metrica di distanza come L2, utilizzare {"_score": "asc"}.

Confronto e ordinamento dei bucket

Utilizza questo modello quando devi confrontare gruppi di entità recuperate utilizzando statistiche calcolate e controllare l’ordine in cui vengono restituiti i bucket. In questo esempio, Milvus raggruppa i prodotti recuperati in base a brand, calcola le metriche di prezzo per ciascun bucket di marca e ordina i bucket in base al prezzo medio.

Se il tuo obiettivo è solo quello di migliorare la diversità dei risultati restituendo una o più entità per ogni valore di campo, utilizza invece la ricerca raggruppata.

La seguente configurazione crea fino a tre bucket per marchio, calcola le metriche per ciascun bucket e ordina i bucket in base al prezzo medio:

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

Passa l’oggetto al parametro ` search_aggregation ` di ` 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,
)

Quando search_aggregation è impostato, PyMilvus non restituisce risultati di entità ordinari in result[0]. Leggi invece la risposta relativa ai bucket da result.agg_buckets[0]. Il parametro output_fields controlla quali campi scalari compaiono in ciascuna mappatura AggregationHit.fields restituita; Milvus può comunque utilizzare campi di origine delle metriche e di ordinamento che non sono elencati in output_fields.

Visualizza l’output di esempio del bucket

L'output seguente è stato acquisito dalla richiesta sopra riportata e serializzato in formato JSON per una maggiore leggibilità. PyMilvus restituisce oggetti ` AggregationBucket ` anziché JSON. Il valore ` key ` è sempre un elenco ordinato di componenti chiave, anche quando ` fields ` contiene un solo campo. Ciò preserva l'ordine dei campi per le chiavi composte.

[
  {
    "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": []
  }
]

Per il singolo vettore di query in questa guida, leggere i bucket di primo livello restituiti da result.agg_buckets[0]. Ogni bucket espone i propri componenti della chiave ordinati, i candidati conservati count, i valori calcolati metrics, i valori rappresentativi hits e i bucket nidificati in sub_groups.

Leggere la configurazione come segue:

ImpostazioneCosa controllaIn questo esempio
fieldsCome Milvus crea le chiavi dei bucketCrea un bucket per ogni valore distinto di brand.
sizeIl numero massimo di bucket restituitiRestituisce fino a tre bucket di marca.
metricsLe statistiche calcolate per ciascun bucketCalcola il numero di prodotti, il prezzo medio e il prezzo minimo.
orderCome Milvus ordina i bucket restituitiOrdina in base al prezzo medio, quindi utilizza la chiave del bucket per risolvere i casi di parità.

Milvus ignora l'limit quando è impostato search_aggregation. Utilizza il valore di root SearchAggregation.size per controllare il numero di bucket di primo livello.

Con queste impostazioni, Milvus restituisce i bucket del Marchio B, del Marchio A e del Marchio C in ordine decrescente di avg_price. Il criterio _key si applica solo quando i bucket hanno lo stesso prezzo medio. Poiché questa configurazione non definisce top_hits, l’elenco hits di ogni bucket è vuoto e il budget candidato per chiave è 1. I conteggi e le metriche visualizzati descrivono quindi un candidato conservato per ogni marchio. Configurare top_hits con un valore maggiore di TopHits.size quando l’aggregazione richiede una finestra di metriche per chiave più ampia.

Metriche e regole di ordinamento

Ogni voce di SearchAggregation.metrics associa un alias definito dall’utente a {operation: source}:

OrigineOperazioni supportateComportamento
Qualsiasi campo nonJSON e non dinamicocountConta i candidati mantenuti il cui campo di origine non è di tipo NULL.
Campo intero o in virgola mobilesum, avg, min, maxEsegue il calcolo sui valori conservati non nulli.
Campo stringa o TIMESTAMPTZ min, maxSeleziona il valore conservato non nullo minimo o massimo.
"*"countConta ogni candidato conservato nel bucket. Il risultato corrisponde a bucket.count.
_scoresum, avg, min, maxAggrega i valori di similarità o distanza ANN per i candidati conservati.

SearchAggregation.order Accetta le seguenti chiavi:

Chiave di ordinamentoSignificato
Alias di una metricaOrdina in base a un valore calcolato in metrics allo stesso livello di aggregazione, ad esempio avg_price.
_countOrdina in base al numero di candidati conservati in ciascun bucket.
_keyOrdina in base alla chiave del bucket anziché a un campo della collezione denominato _key.

Ogni voce di ` order ` associa una chiave a ` "asc" ` o ` "desc"`. Milvus valuta più voci dalla prima all’ultima. Se si omette ` order`, Milvus mantiene l’ordine di individuazione dei bucket dall’insieme dei candidati conservati.

Per ordinare i bucket in base alla qualità della corrispondenza vettoriale, calcolare innanzitutto una metrica a livello di bucket da _score, quindi utilizzare l’alias della metrica in order. Non è possibile utilizzare direttamente _score come chiave di ordinamento dei bucket poiché ogni bucket può contenere più punteggi di entità. Ad esempio, con COSINE o IP:

aggregation = SearchAggregation(
    fields=["brand"],
    size=3,
    metrics={"max_score": {"max": "_score"}},
    order=[{"max_score": "desc"}],
)

Con L2, calcolare il valore minimo di _score e ordinare l’alias della metrica in ordine crescente, in modo che i bucket con la distanza minima vengano visualizzati per primi.

Creazione di chiavi di bucket composte

Per creare una chiave di bucket composita, passare più nomi di campo nello stesso elenco:

aggregation = SearchAggregation(
    # Combine brand and color to form a composite bucket key.
    fields=["brand", "color"],
    size=6,
)

Questa configurazione può produrre chiavi come (Brand A, black), (Brand A, blue) e (Brand B, white). Due entità condividono un bucket solo quando entrambi i valori corrispondono. Milvus mantiene l’ordine dell’elenco, quindi brand è il primo componente della chiave e color è il secondo. Quando si utilizza _key in order, Milvus confronta i componenti della chiave composita nello stesso ordine. Passare più stringhe in un unico elenco piatto; gli elenchi annidati non sono supportati.

size=6 è il numero massimo di bucket compositi restituiti a questo livello di aggregazione. I dati di esempio contengono cinque combinazioni distinte di marchio e colore, quindi è possibile restituirle tutte e cinque. Nel limite delle voci restituite, questa richiesta contribuisce con 1 query vector × 6 buckets × 1 = 6 voci di risultato configurate.

Più campi in un unico elenco SearchAggregation.fields creano una chiave di bucket composita a quel livello di aggregazione. Per creare una gerarchia di bucket padre-figlio, utilizzare un'aggregazione annidata.

Gli esempi che seguono ridefinisc aggregation. Passare l’oggetto aggiornato allo stesso parametro search_aggregation ed eseguire nuovamente la chiamata di ricerca.

Mostra risultati rappresentativi da ciascun bucket

Includere entità rappresentative quando l’applicazione deve mostrare prodotti effettivi da ciascun bucket. In questo esempio, Milvus restituisce fino a due prodotti da ciascun bucket di marca, ordinati per valutazione e poi per punteggio vettoriale.

Configurare TopHits come segue:

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

Visualizza un bucket con risultati rappresentativi

Il seguente bucket del marchio A è stato estratto dalla richiesta sopra riportata e serializzato in formato JSON per facilitarne la lettura.

{
  "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": []
}

ParametroScopo
top_hitsOpzionale. Configura le entità rappresentative per questo livello di aggregazione. Se omesso, " bucket.hits " risulta vuoto e il budget candidato per chiave viene impostato di default a uno.
TopHits.sizeRestituisce fino a due entità rappresentative da ciascun bucket selezionato e imposta il budget candidato per chiave a due per l'intero albero di aggregazione.
TopHits.sortOrdina le entità all’interno di ciascun bucket utilizzando i criteri elencati.

Configurare ` top_hits ` quando l’applicazione necessita di entità rappresentative o quando i conteggi e le metriche richiedono una finestra di candidati per chiave più ampia. Un valore maggiore di ` TopHits.size ` aumenta sia il budget dei candidati sia il calcolo del numero massimo di voci restituite in `Limits`.

SearchAggregation.order Ordina i bucket, mentre l’opzione « TopHits.sort » ordina le entità conservate all’interno di ciascun bucket. L’ordine di ordinamento non modifica quali candidati sono stati conservati per l’ count e le metriche. L’opzione « TopHits.sort » accetta nomi di campi scalari comparabili supportati e il campo integrato « _score », che rappresenta la somiglianza o la distanza ANN. Milvus valuta le voci « sort » dalla prima all’ultima. In questo esempio, ordina i prodotti in base a rating dal valore più alto a quello più basso e utilizza _score solo quando due valutazioni sono uguali. Poiché la configurazione utilizza COSINE, l’ordinamento decrescente _score posiziona per primo il prodotto più simile.

I campi utilizzati da metrics o TopHits.sort non devono necessariamente comparire in output_fields. Milvus recupera tali campi internamente, ma solo i campi esplicitamente elencati in output_fields vengono inclusi nella mappatura fields di ciascun risultato restituito. Le chiavi primarie e i punteggi vettoriali rimangono disponibili tramite AggregationHit.pk e AggregationHit.score.

Ogni AggregationHit restituito espone la propria chiave primaria in pk, il punteggio vettoriale in score e i campi di output richiesti in fields.

Raggruppamento dei risultati su più livelli

Utilizzare l’aggregazione annidata quando è necessario un livello di bucket all’interno di un altro. In questo esempio, Milvus crea prima i bucket di categoria, quindi crea i bucket di marchio all’interno di ciascuna categoria.

L’aggregazione figlia riceve solo le entità assegnate al proprio bucket padre. fields controlla la chiave del bucket a ciascun livello di aggregazione, mentre sub_aggregation crea la gerarchia padre-figlio.

La configurazione riportata di seguito crea un bucket di categoria con la chiave (running_shoes). All’interno di quel bucket padre, l’aggregazione figlia crea bucket di marchio separati con chiavi quali (Brand A), (Brand B) e (Brand C).

Parent bucket key:
(running_shoes)

Child bucket keys:
├── (Brand A)
├── (Brand B)
└── (Brand C)

Ogni livello può utilizzare più campi in modo indipendente. Ad esempio, l’utilizzo di fields=["brand", "color"] nell’aggregazione figlia creerebbe chiavi figlie composte come (Brand A, black).

La seguente configurazione implementa questa gerarchia:

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

Visualizzazione del risultato di un bucket annidato

Il seguente estratto serializzato mostra il bucket padre running_shoes e il suo bucket figlio Brand B. I bucket figli Brand A e Brand C sono stati omessi per brevità.

{
  "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": []
    }
  ]
}

Il risultato visualizzato rappresenta il percorso del bucket (running_shoes) → (Brand B), non una singola chiave composita del bucket (running_shoes, Brand B).

Milvus seleziona innanzitutto fino a due bucket di categoria, ordinati in base a product_count. Successivamente esegue sub_aggregation in modo indipendente all’interno di ciascuna categoria selezionata e restituisce fino a tre bucket di marchio, ordinati in base a avg_rating.

Nell’output sopra riportato:

  • Il bucket radice running_shoes contiene quattro candidati selezionati tra le sue chiavi composite figlie. I suoi metrics contengono i valori di livello radice avg_price e product_count.
  • L'elenco sub_groups del bucket radice contiene i bucket secondari relativi ai marchi. Il bucket "Brand B" visualizzato contiene un candidato conservato e i propri valori avg_rating e brand_count.
  • L’elenco hits del bucket radice è vuoto perché l’aggregazione radice non configura top_hits. Il bucket figlio del marchio B contiene un risultato rappresentativo perché top_hits è configurato in sub_aggregation.

Domande frequenti

Quanto sono accurati i conteggi e le metriche dei bucket?

L’aggregazione di ricerca riassume i candidati ANN conservati. Non esegue un’aggregazione completa della raccolta.

La conservazione dei candidati prevede due fasi di approssimazione. La ricerca ANN può omettere entità rilevanti della collezione, mentre la fase di raggruppamento conserva al massimo i candidati più grandi TopHits.size per ciascuna chiave composita completa. Se nessun livello configura top_hits, questo limite per chiave è pari a uno.

Ad esempio, supponiamo che una collezione contenga 5.000 prodotti del Marchio A e che molti siano rilevanti per la query vettoriale. Se l’aggregazione utilizza ` TopHits(size=4)`, il bucket del Marchio A può conservare al massimo quattro candidati per una chiave composita completa. Il suo ` count ` e le metriche descrivono quei candidati conservati, non tutti i prodotti rilevanti del Marchio A e non tutte le 5.000 entità della collezione.

L’approssimazione è particolarmente rilevante quando l’ order utilizza un alias di metrica. Le variazioni nel recall della ricerca possono modificare i valori delle metriche e, di conseguenza, determinare quali bucket rientrano nell’ SearchAggregation.size. L’aggregazione annidata può amplificare questo effetto poiché ogni livello figlio opera sulle entità disponibili nel proprio bucket padre.

Se sono necessarie statistiche esatte su ogni entità corrispondente, utilizzare un flusso di lavoro di aggregazione con query esatta anziché l’aggregazione di ricerca.

Scegli in base alla forma principale dei risultati dell’applicazione:

Esigenza principalePreferireRisposta da utilizzare
Restituisce un elenco standard di entità ordinato per rilevanza con un minor numero di valori ripetuti in un campo di raggruppamentoRicerca raggruppataRisultati di ricerca piatti per ciascun vettore di query
Esamina o confronta i gruppi come bucket, con chiavi, conteggi, metriche, ordinamento, risultati rappresentativi o bucket secondariAggregazione della ricercaAggregationBucket oggetti in result.agg_buckets

Anche quando l’aggregazione di ricerca configura top_hits, la sua risposta principale rimane un albero di bucket. La ricerca raggruppata rimane utile quando l’applicazione elabora già risultati di ricerca ordinari e mira principalmente alla diversità dei risultati.

Le API si escludono a vicenda. PyMilvus genera un'eccezione di tipo ` ParamError ` quando ` search_aggregation ` viene combinato con ` group_by_field ` o ` group_by_fields ` nella stessa richiesta.