SuchaggregationCompatible with Milvus 3.0.x
Wenn ein Käufer nach „schwarzen Laufschuhen für das tägliche Training“ sucht, ordnet die Annäherungsnachbarschaftssuche (ANN) die Produkte nach Vektorähnlichkeit und liefert eine flache Top-K-Liste. Die Ergebnisse können zwar relevant, aber auch repetitiv sein: Im folgenden Beispiel stammen vier der ersten sechs Ergebnisse von Marke A, während Marke B und Marke C jeweils nur einmal vorkommen.
Eine flache Liste kann keine bucket-orientierte Zusammenfassung liefern. Eine Anwendung muss möglicherweise Marken anhand der Anzahl der beibehaltenen Kandidaten oder des Durchschnittspreises vergleichen, eine kleine Anzahl repräsentativer Produkte jeder Marke untersuchen oder die Ergebnisse in mehrere Bucket-Ebenen organisieren.
Die Suchaggregation ordnet die beibehaltenen ANN-Kandidaten anhand ausgewählter Skalarfelder in Buckets ein. In diesem Beispiel wird jede Marke zu einem separaten Bucket. Milvus kann Statistiken für jeden Bucket berechnen, die Buckets ordnen und repräsentative Produkte zuordnen. Die Anwendung nutzt diese „Bucket-First“-Antwort über „ result.agg_buckets “.
Ein flaches Suchergebnis für Laufschuhe wird zu einer Reihe vergleichbarer Marken-Buckets
Die Suchaggregation führt keine exakte Aggregation der gesamten Sammlung durch. Das Vorhandensein von Buckets, deren Anzahl, Metriken, Reihenfolge und repräsentative Treffer hängen von den Kandidaten ab, die in den ANN- und Gruppierungsphasen beibehalten wurden.
So funktioniert es
ANN-Kandidaten, gruppiert nach Bucket-Schlüsseln und zurückgegeben mit Anzahlen, Metriken und repräsentativen Treffern
Kandidaten abrufen. Milvus führt eine ANN-Suche durch, um die Entitäten zu finden, die dem Abfragevektor am nächsten liegen. Die Gruppierungsphase behält dann für jeden vollständigen zusammengesetzten Schlüssel eine begrenzte Anzahl von Kandidaten bei. Dieses Kandidatenkontingent pro Schlüssel entspricht dem größten Wert von „
TopHits.size“ an beliebiger Stelle im Aggregationsbaum oder dem Wert „1“, wenn keine Ebene „top_hits“ konfiguriert hat.Bucket-Erstellung. „
SearchAggregation.fields“ definiert den Bucket-Schlüssel. Jede eindeutige Kombination von Feldwerten erzeugt einen separaten Schlüssel. In der Abbildung erzeugt „fields=["brand"]“ die Bucket-Schlüssel „(Brand A)“, „(Brand B)“ und „(Brand C)“. Beibehaltene Kandidaten mit demselben Schlüssel gehören zum selben Bucket und tragen zu dessen „count“ bei. „SearchAggregation.size“ begrenzt die Anzahl der von Milvus zurückgegebenen Buckets.Berechnung und Rückgabe der Ergebnisse. Jeder zurückgegebene Bucket enthält seinen Schlüssel und die Anzahl der beibehaltenen Kandidaten. Milvus kann außerdem konfigurierte Metriken berechnen, die Buckets sortieren, repräsentative Entitäten zurückgeben und untergeordnete Buckets erstellen. Jeder
AggregationBucketunterresult.agg_bucketsstelltkey,count,metrics,hitsundsub_groupsbereit. Wenn die Suchaggregation aktiviert ist, ist die normale Suchtrefferliste leer.
In der Abbildung stellt „ TopHits.size=4 “ ein Kandidatenbudget von vier pro Schlüssel bereit, sodass die vier beibehaltenen Kandidaten der Marke A die Ergebnisse „ count: 4 “ liefern. Die fertige Karte für Marke A zeigt nur zwei der vier zurückgegebenen repräsentativen Treffer, um die Darstellung übersichtlich zu halten.
Bei „ sub_aggregation “ wiederholt Milvus die Schritte 2 und 3 innerhalb jedes übergeordneten Buckets. Änderungen am ANN-Recall oder am Kandidatenbudget pro Schlüssel können die Anzahl der Buckets, Metriken, Reihenfolge, Treffer und verschachtelten Ergebnisse beeinflussen.
Einschränkungen
Bevor Sie die Suchaggregation verwenden, beachten Sie bitte die folgenden Einschränkungen:
Verschachtelte Aggregationen: Eine Anfrage kann eine Stamm-
SearchAggregationund bis zu drei verschachteltesub_aggregation-Ebenen enthalten, also insgesamt maximal vier Ebenen. Über alle Ebenen hinweg können höchstens 10 Felder zur Erstellung von Bucket-Schlüsseln verwendet werden.Felder zur Erstellung von Bucket-Schlüsseln: „
SearchAggregation.fields“ unterstützt boolesche, ganzzahlige, „VARCHAR“- und „TIMESTAMPTZ“-Felder. Es unterstützt keine „FLOAT“-Felder, „DOUBLE“-Felder, „ARRAY“-Felder, „JSON“-Felder, „GEOMETRY“-Felder, „TEXT“-Felder, Vektor- oder dynamische Felder.Metrikfelder:
countakzeptiert"*"oder jedes nicht-JSON- und nicht-dynamische Feld und überspringtNULL-Werte, wenn ein Feld angegeben ist.sumundavgakzeptieren Ganzzahl- und Gleitkomma-Felder.minundmaxakzeptieren zusätzlich Zeichenfolgen- undTIMESTAMPTZ-Felder.Sortierfelder für Top-Treffer: „
TopHits.sort“ akzeptiert vergleichbare boolesche, ganzzahlige, Gleitkomma-, Zeichenfolgen- und „TIMESTAMPTZ“-Felder sowie „_score“. Es unterstützt keine „ARRAY“-Felder, „JSON“-Felder, „GEOMETRY“-Felder, Vektor- oder dynamische Felder.Kandidatenbudget: Der größteWert für „
TopHits.size“ an beliebiger Stelle im Aggregationsbaum entspricht auch der Anzahl der pro vollständigem zusammengesetztem Schlüssel beibehaltenen Kandidaten. Wenn auf keiner Ebene „top_hits“ konfiguriert ist, behält Milvus einen Kandidaten pro Schlüssel bei. „count“ und Metriken werden anhand dieser beibehaltenen Kandidaten berechnet, sodass eine Änderung von „TopHits.size“ diese Werte beeinflussen kann.Nullfähige Bucket-Felder: Ein Wert „
NULL“ bildet einen eigenen Bucket-Schlüssel. Um den Null-Bucket auszuschließen, fügen Sie der Suchanfrage einen Filter wie „brand is not null“ hinzu.Wiederholte Felder: Dasselbe Feld darf nicht in mehr als einer „
SearchAggregation.fields“-Liste vorkommen. Wenn beispielsweise die Stammaggregation „fields=["category"]“ verwendet, darf ein verschachtelter „sub_aggregation“ nicht zusätzlich „fields=["category"]“ verwenden.Nicht unterstützte Kombinationen: „Search Aggregation“ kann nicht mit einem von Null verschiedenen „
offset“, Suchiteratoren, der hybriden Suche, einem Highlighter oder der Gruppierungssuche kombiniert werden. Ein Wert von „0“ auf oberster Ebene für „offset“ entspricht dem Weglassen des Parameters. In REST-v2-Suchanfragen können „searchAggregation“ und „ids“ nicht gemeinsam angegeben werden.Zurückgegebene Einträge: Standardmäßig lehnt Milvus eine Suchaggregationsanfrage ab, wenn die berechnete maximale Anzahl der Ergebniseinträge 10.000 überschreitet. Dieser Schwellenwert wird durch „
proxy.maxSearchAggregationResultEntries“ gesteuert. Setzen Sie den Konfigurationswert auf „0“ oder eine negative Zahl, um diese Prüfung zu deaktivieren.Milvus berechnet dieses Maximum wie folgt:
number of query vectors × product of the effective search_size at every aggregation level × largest TopHits.size at any levelFür diese serverseitige Berechnung ist der effektive Wert von „
search_size“ auf einer Ebene entweder der explizit konfigurierte Wert „search_size“ oder der Wert von „size“ dieser Ebene, wenn „search_size“ weggelassen wird. Die in diesem Leitfaden verwendete PyMilvus-API stellt „search_size“ derzeit nicht zur Verfügung, daher verwenden PyMilvus-Anfragen für diese Berechnung den Wert von „size“ der jeweiligen Ebene. Verwenden Sie „1“ als letzten Faktor, wenn auf keiner Ebene „TopHits“ konfiguriert ist. Beispielsweise ergibt sich bei einem Abfragevektor, 10 Root-Buckets, fünf Child-Buckets pro Root-Bucket und zwei Treffern pro Child-Bucket ein berechnetes Maximum von:1 × 10 × 5 × 2 = 100
Verwenden Sie die Suchaggregation
Wählen Sie ein Beispiel entsprechend Ihrem Ziel aus:
| Gehen Sie zu | Beschreibung | Wichtige Einstellungen |
|---|---|---|
| Buckets vergleichen und sortieren | Berechnen Sie Statistiken pro Bucket, um Buckets zu vergleichen, und sortieren Sie anschließend die zurückgegebenen Buckets nach Metriken, Zählwerten oder Schlüsseln. | fields, size, metrics, order |
| Zeigen Sie repräsentative Ergebnisse aus jedem Bucket an | Geben Sie eine begrenzte Anzahl von Entitäten aus jedem Bucket zurück und sortieren Sie diese Entitäten unabhängig voneinander nach Skalarfeldern oder Vektorwerten. | top_hits, TopHits.size, TopHits.sort |
| Ergebnisse auf mehreren Ebenen gruppieren | Organisieren Sie die Ergebnisse in über- und untergeordnete Bucket-Ebenen, um mehrere Dimensionen nacheinander zu analysieren. | sub_aggregation |
Die folgenden Beispiele verwenden eine Produktsammlung mit den Feldern „Marke“, „Kategorie“, „Farbe“, „Preis“ und „Bewertung“. Alle Markennamen, Produktnamen, Preise, Bewertungen und Suchergebnisse sind synthetische Beispieldaten. Erweitern Sie den folgenden Abschnitt, um die Sammlung zu erstellen und die gemeinsamen Suchvariablen zu definieren.
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": {},
}
Die obige Konfiguration richtet „ COSINE “ sowohl für den Vektorindex als auch für die Suchparameter ein. Daher verwenden spätere Beispiele „ {"_score": "desc"} “, um eine höhere Kosinusähnlichkeit an erster Stelle zu platzieren. Für eine Distanzmetrik wie „ L2 “ verwenden Sie „ {"_score": "asc"} “.
Buckets vergleichen und sortieren
Verwenden Sie dieses Muster, wenn Sie Gruppen von abgerufenen Entitäten anhand berechneter Statistiken vergleichen und die Reihenfolge steuern möchten, in der die Buckets zurückgegeben werden. In diesem Beispiel gruppiert Milvus die abgerufenen Produkte nach „ brand “, berechnet Preismetriken für jeden Marken-Bucket und sortiert die Buckets nach dem Durchschnittspreis.
Wenn Ihr Ziel lediglich darin besteht, die Vielfalt der Ergebnisse zu verbessern, indem Sie eine oder mehrere Entitäten pro Feldwert zurückgeben, verwenden Sie stattdessen die gruppierte Suche.
Die folgende Konfiguration erstellt bis zu drei Marken-Buckets, berechnet Metriken für jeden Bucket und sortiert die Buckets nach Durchschnittspreis:
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"},
],
)
Übergeben Sie das Objekt an den Parameter „ search_aggregation “ von „ 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,
)
Wenn „ search_aggregation “ gesetzt ist, gibt PyMilvus in „ result[0] “ keine gewöhnlichen Entitätstreffer zurück. Lesen Sie stattdessen die Bucket-Antwort aus „ result.agg_buckets[0] “ aus. Der Parameter „ output_fields “ steuert, welche Skalarfelder in jedem zurückgegebenen „ AggregationHit.fields “-Mapping erscheinen; Milvus kann weiterhin Metrikquellen- und Sortierfelder verwenden, die nicht in „ output_fields “ aufgeführt sind.
Die folgende Ausgabe wurde aus der obigen Anfrage erfasst und zur besseren Lesbarkeit als JSON serialisiert. PyMilvus gibt „ AggregationBucket “-Objekte anstelle von JSON zurück. Der Wert „ key “ ist immer eine geordnete Liste von Schlüsselkomponenten, selbst wenn „ fields “ nur ein Feld enthält. Dadurch bleibt die Feldreihenfolge bei zusammengesetzten Schlüsseln erhalten.
[
{
"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": []
}
]
Für den einzelnen Abfragevektor in dieser Anleitung lesen Sie die zurückgegebenen Buckets der obersten Ebene aus ` result.agg_buckets[0]` aus. Jeder Bucket legt seine geordneten Schlüsselkomponenten, die beibehaltenen Kandidaten ` count`, die berechneten Werte ` metrics`, die repräsentativen Werte ` hits` sowie die verschachtelten Buckets in ` sub_groups` offen.
Lesen Sie die Konfiguration wie folgt ein:
| Einstellung | Was sie steuert | In diesem Beispiel |
|---|---|---|
fields | Wie Milvus Bucket-Schlüssel erstellt | Erstellt für jeden eindeutigen Wert von „ brand “ einen Bucket. |
size | Die maximale Anzahl der zurückgegebenen Buckets | Es werden bis zu drei Marken-Buckets zurückgegeben. |
metrics | Die für jeden Bucket berechneten Statistiken | Berechnet die Produktanzahl, den Durchschnittspreis und den Mindestpreis. |
order | Wie Milvus die zurückgegebenen Buckets sortiert | Sortiert nach Durchschnittspreis und verwendet anschließend den Bucket-Schlüssel, um bei Gleichstand zu entscheiden. |
Milvus ignoriert „ limit “, wenn „ search_aggregation “ gesetzt ist. Verwenden Sie den Wert „ SearchAggregation.size “ der obersten Ebene, um die Anzahl der Buckets der obersten Ebene zu steuern.
Mit diesen Einstellungen gibt Milvus die Buckets „Marke B“, „Marke A“ und „Marke C“ in absteigender Reihenfolge nach „ avg_price “ zurück. Das Kriterium „ _key “ gilt nur, wenn Buckets denselben Durchschnittspreis aufweisen. Da in dieser Konfiguration „ top_hits “ nicht definiert ist, ist die Liste „ hits “ jedes Buckets leer und das Kandidatenbudget pro Schlüssel beträgt „ 1 “. Die angezeigten Zählwerte und Metriken beschreiben daher jeweils einen beibehaltenen Kandidaten pro Marke. Konfigurieren Sie „ top_hits “ mit einem größeren „ TopHits.size “, wenn die Aggregation ein breiteres Metrikfenster pro Schlüssel benötigt.
Jeder Eintrag unter „ SearchAggregation.metrics “ ordnet einen benutzerdefinierten Alias dem Eintrag „ {operation: source} “ zu:
| Quelle | Unterstützte Operationen | Verhalten |
|---|---|---|
Jedes Feld, das weder „JSON “ noch dynamisch ist | count | Zählt die verbleibenden Kandidaten, deren Quellfeld nicht „ NULL “ ist. |
| Ganzzahl- oder Gleitkommafeld | sum, „ avg “, „ min “, max | Berechnet über nicht-null-Werte der beibehaltenen Werte. |
Zeichenfolgen- oder „ TIMESTAMPTZ “-Feld | min, max | Wählt den kleinsten oder größten beibehaltenen Wert aus, der nicht null ist. |
"*" | count | Zählt jeden beibehaltenen Kandidaten im Bucket. Das Ergebnis entspricht „ bucket.count “. |
_score | sum, „ avg “, „ min “, max | Aggregiert ANN-Ähnlichkeits- oder -Abstandswerte für beibehaltene Kandidaten. |
SearchAggregation.order Akzeptiert die folgenden Schlüssel:
| Reihenfolgeschlüssel | Bedeutung |
|---|---|
| Ein Alias für eine Metrik | Sortiert nach einem Wert, der in „ metrics “ auf derselben Aggregationsebene berechnet wird, z. B. „ avg_price “. |
_count | Sortiert nach der Anzahl der in jedem Bucket verbleibenden Kandidaten. |
_key | Sortiert nach dem Bucket-Schlüssel anstelle eines Sammlungsfelds namens „ _key “. |
Jeder Eintrag in „ order “ ordnet einen Schlüssel „ "asc" “ oder „ "desc" “ zu. Milvus wertet mehrere Einträge vom ersten bis zum letzten aus. Wenn Sie „ order “ weglassen, behält Milvus die Reihenfolge der Bucket-Ermittlung aus der Menge der beibehaltenen Kandidaten bei.
Um Buckets nach der Qualität der Vektorübereinstimmung zu sortieren, berechnen Sie zunächst eine Metrik auf Bucket-Ebene aus _score und verwenden Sie dann den Metrik-Alias in order. Sie können _score nicht direkt als Schlüssel für die Bucket-Reihenfolge verwenden, da jeder Bucket mehrere Entitäts-Scores enthalten kann. Beispielsweise bei COSINE oder IP:
aggregation = SearchAggregation(
fields=["brand"],
size=3,
metrics={"max_score": {"max": "_score"}},
order=[{"max_score": "desc"}],
)
Berechnen Sie bei „ L2 “ den minimalen Wert von „ _score “ und sortieren Sie den Metrik-Alias in aufsteigender Reihenfolge, sodass Buckets mit dem geringsten Abstand an erster Stelle stehen.
Um einen zusammengesetzten Bucket-Schlüssel zu erstellen, übergeben Sie mehrere Feldnamen in derselben Liste:
aggregation = SearchAggregation(
# Combine brand and color to form a composite bucket key.
fields=["brand", "color"],
size=6,
)
Diese Konfiguration kann Schlüssel wie „ (Brand A, black) “, „ (Brand A, blue) “ und „ (Brand B, white) “ erzeugen. Zwei Entitäten teilen sich einen Bucket nur dann, wenn beide Werte übereinstimmen. Milvus behält die Reihenfolge der Liste bei, sodass „ brand “ die erste Schlüsselkomponente und „ color “ die zweite ist. Wenn „ _key “ in „ order “ verwendet wird, vergleicht Milvus die Komponenten des zusammengesetzten Schlüssels in derselben Reihenfolge. Übergeben Sie mehrere Zeichenfolgen in einer flachen Liste; verschachtelte Listen werden nicht unterstützt.
size=6 ist die maximale Anzahl der auf dieser Aggregationsebene zurückgegebenen zusammengesetzten Buckets. Die Beispieldaten enthalten fünf verschiedene Marken-Farb-Kombinationen, sodass alle fünf zurückgegeben werden können. Im Rahmen der Begrenzung der zurückgegebenen Einträge trägt diese Anfrage 1 query vector × 6 buckets × 1 = 6 konfigurierte Ergebniseinträge bei.
Mehrere Felder in einer „ SearchAggregation.fields “-Liste bilden einen zusammengesetzten Bucket-Schlüssel auf dieser Aggregationsebene. Um eine Eltern-Kind-Bucket-Hierarchie zu erstellen, verwenden Sie eine verschachtelte Aggregation.
Die folgenden Beispiele definieren „ aggregation “ neu. Übergeben Sie das aktualisierte Objekt an denselben Parameter „ search_aggregation “ und führen Sie den Suchaufruf erneut aus.
Zeigen Sie repräsentative Ergebnisse aus jedem Bucket an
Beziehen Sie repräsentative Entitäten ein, wenn die Anwendung tatsächliche Produkte aus jedem Bucket anzeigen soll. In diesem Beispiel gibt Milvus bis zu zwei Produkte aus jedem Marken-Bucket zurück, sortiert nach Bewertung und anschließend nach Vektorwert.
Konfigurieren Sie „ TopHits “ wie folgt:
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"},
],
),
)
Der folgende Bucket „Marke A“ wurde aus der obigen Anfrage extrahiert und zur besseren Lesbarkeit als JSON serialisiert.
{
"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": []
}
| Parameter | Zweck |
|---|---|
top_hits | Optional. Konfiguriert repräsentative Entitäten für diese Aggregationsebene. Wird dieser Parameter weggelassen, ist „ bucket.hits “ leer und das Kandidatenbudget pro Schlüssel wird standardmäßig auf eins gesetzt. |
TopHits.size | Gibt bis zu zwei repräsentative Entitäten aus jedem ausgewählten Bucket zurück und setzt das Kandidatenbudget pro Schlüssel für den gesamten Aggregationsbaum auf zwei fest. |
TopHits.sort | Ordnet Entitäten innerhalb jedes Buckets anhand der aufgeführten Kriterien. |
Konfigurieren Sie „ top_hits “, wenn die Anwendung repräsentative Entitäten benötigt oder wenn Zählungen und Metriken ein breiteres Fenster für Kandidaten pro Schlüssel erfordern. Ein größeres „ TopHits.size “ erhöht sowohl das Kandidatenbudget als auch die maximale Anzahl der zurückgegebenen Einträge in „Limits“.
SearchAggregation.order sortiert die Buckets, während „ TopHits.sort “ die beibehaltenen Entitäten innerhalb jedes Buckets sortiert. Die Sortierreihenfolge hat keinen Einfluss darauf, welche Kandidaten für „ count “ und Metriken beibehalten wurden. „ TopHits.sort “ akzeptiert unterstützte, vergleichbare Skalarfeldnamen sowie das integrierte Feld „ _score “, das die ANN-Ähnlichkeit oder den ANN-Abstand darstellt. Milvus wertet die Einträge in „ sort “ von vorne nach hinten aus. In diesem Beispiel sortiert es Produkte nach „ rating “ vom höchsten zum niedrigsten Wert und verwendet „ _score “ nur, wenn zwei Bewertungen gleich sind. Da die Konfiguration „ COSINE “ verwendet, wird bei absteigender Sortierung nach „ _score “ das ähnlichere Produkt an erster Stelle platziert.
Die von „ metrics “ oder „ TopHits.sort “ verwendeten Felder müssen nicht in „ output_fields “ erscheinen. Milvus ruft diese Felder intern ab, aber nur Felder, die explizit in „ output_fields “ aufgeführt sind, werden in das „ fields “-Mapping jedes zurückgegebenen Treffers aufgenommen. Primärschlüssel und Vektorwerte bleiben über „ AggregationHit.pk “ und „ AggregationHit.score “ verfügbar.
Jedes zurückgegebene „ AggregationHit “ gibt seinen Primärschlüssel unter pk, den Vektorwert unter score und die angeforderten Ausgabefelder unter fields bekannt.
Ergebnisse auf mehreren Ebenen gruppieren
Verwenden Sie verschachtelte Aggregation, wenn Sie eine Ebene von Buckets innerhalb einer anderen benötigen. In diesem Beispiel erstellt Milvus zunächst Kategorie-Buckets und anschließend Marken-Buckets innerhalb jeder Kategorie.
Die untergeordnete Aggregation erhält nur die Entitäten, die ihrem übergeordneten Bucket zugeordnet sind. „ fields “ steuert den Bucket-Schlüssel auf jeder Aggregationsebene, während „ sub_aggregation “ die Eltern-Kind-Hierarchie erstellt.
Die folgende Konfiguration erstellt einen Kategorie-Bucket mit dem Schlüssel „ (running_shoes) “. Innerhalb dieses übergeordneten Buckets erstellt die untergeordnete Aggregation separate Marken-Buckets mit Schlüsseln wie „ (Brand A) “, „ (Brand B) “ und „ (Brand C) “.
Parent bucket key:
(running_shoes)
Child bucket keys:
├── (Brand A)
├── (Brand B)
└── (Brand C)
Jede Ebene kann unabhängig voneinander mehrere Felder verwenden. Würde man beispielsweise „ fields=["brand", "color"] “ in der untergeordneten Aggregation verwenden, würden zusammengesetzte untergeordnete Schlüssel wie „ (Brand A, black) “ entstehen.
Die folgende Konfiguration implementiert diese Hierarchie:
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"}],
),
),
)
Der folgende serialisierte Auszug zeigt den übergeordneten Bucket „ running_shoes “ und dessen untergeordneten Bucket „Brand B“. Die untergeordneten Buckets „Brand A“ und „Brand C“ wurden der Übersichtlichkeit halber weggelassen.
{
"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": []
}
]
}
Das angezeigte Ergebnis stellt den Bucket-Pfad „ (running_shoes) → (Brand B) “ dar, nicht einen einzelnen zusammengesetzten Bucket-Schlüssel wie „ (running_shoes, Brand B) “.
Milvus wählt zunächst bis zu zwei Kategorie-Buckets aus, sortiert nach „ product_count “. Anschließend führt es „ sub_aggregation “ unabhängig innerhalb jeder ausgewählten Kategorie aus und gibt bis zu drei Marken-Buckets zurück, sortiert nach „ avg_rating “.
In der obigen Ausgabe:
- Der Stamm-Bucket „
running_shoes“ enthält vier beibehaltene Kandidaten über seine untergeordneten zusammengesetzten Schlüssel hinweg. Seine „metrics“ enthalten die Werte „avg_price“ und „product_count“ auf Stammebene. - Die Liste „
sub_groups“ des Stamm-Buckets enthält die untergeordneten Marken-Buckets. Der angezeigte Marken-B-Bucket enthält einen beibehaltenen Kandidaten sowie seine eigenen Werte für „avg_rating“ und „brand_count“. - Die Liste „
hits“ des Stamm-Buckets ist leer, da die Stammaggregation „top_hits“ nicht konfiguriert. Der untergeordnete Bucket „Marke B“ enthält einen repräsentativen Treffer, da „top_hits“ in „sub_aggregation“ konfiguriert ist.
FAQ
Wie genau sind Bucket-Zählungen und Metriken?
Die Suchaggregation fasst die beibehaltenen ANN-Kandidaten zusammen. Es wird keine Aggregation der gesamten Sammlung durchgeführt.
Die Beibehaltung von Kandidaten erfolgt in zwei Annäherungsstufen. Die ANN-Suche kann relevante Sammlungsentitäten auslassen, und in der Gruppierungsphase werden für jeden vollständigen zusammengesetzten Schlüssel höchstens die größten „ TopHits.size “-Kandidaten beibehalten. Wenn auf keiner Ebene „ top_hits “ konfiguriert ist, beträgt diese Begrenzung pro Schlüssel eins.
Angenommen, eine Sammlung enthält 5.000 Produkte der Marke A, von denen viele für die Vektorabfrage relevant sind. Wenn die Aggregation „ TopHits(size=4) “ verwendet, kann der Bucket „Marke A“ höchstens vier Kandidaten für einen vollständigen zusammengesetzten Schlüssel behalten. Die Werte für „ count “ und die Metriken beschreiben diese beibehaltenen Kandidaten, nicht alle relevanten Produkte der Marke A und nicht alle 5.000 Entitäten der Sammlung.
Die Annäherung spielt vor allem dann eine Rolle, wenn „ order “ einen Metrik-Alias verwendet. Änderungen des Such-Recalls können die Metrikwerte verändern und somit beeinflussen, welche Buckets in „ SearchAggregation.size “ passen. Eine verschachtelte Aggregation kann diesen Effekt verstärken, da jede untergeordnete Ebene auf die in ihrem übergeordneten Bucket verfügbaren Entitäten angewendet wird.
Wenn Sie exakte Statistiken über jede übereinstimmende Entität benötigen, verwenden Sie anstelle der Suchaggregation einen Workflow zur exakten Abfrageaggregation.
Wie unterscheidet sich die Suchaggregation von der Gruppierungssuche?
Treffen Sie Ihre Wahl anhand der primären Ergebnisform der Anwendung:
| Hauptanforderung | Bevorzugt | Zu verarbeitende Antwort |
|---|---|---|
| Gibt eine standardmäßige, nach Rang geordnete Entitätsliste mit weniger Wiederholungen in einem Gruppierungsfeld zurück | Gruppierte Suche | Flache Suchtreffer für jeden Abfragevektor |
| Gruppen als Buckets mit Schlüsseln, Zählwerten, Metriken, Reihenfolge, repräsentativen Treffern oder untergeordneten Buckets untersuchen oder vergleichen | Suchaggregation | AggregationBucket Objekte in result.agg_buckets |
Selbst wenn bei der Suchaggregation „ top_hits “ konfiguriert ist, bleibt die primäre Antwort ein Bucket-Baum. Die Gruppensuche bleibt nützlich, wenn die Anwendung bereits gewöhnliche Suchtreffer verarbeitet und in erster Linie eine Vielfalt an Ergebnissen anstrebt.
Die APIs schließen sich gegenseitig aus. PyMilvus löst eine „ ParamError “-Ausnahme aus, wenn „ search_aggregation “ in derselben Anfrage mit „ group_by_field “ oder „ group_by_fields “ kombiniert wird.