Gruppierung von Suchergebnissen mit StructArray

Verwenden Sie diese Seite, um Suchergebnisse auf StructArray-Ebene nach der übergeordneten Entität zu gruppieren. Bei der Suche auf Elementebene können mehrere Treffer derselben Entität zurückgegeben werden, wenn mehrere Struct-Elemente der Abfrage entsprechen. Durch die Gruppierung werden diese Elementtreffer zusammengefasst, sodass jede übergeordnete Entität höchstens einmal erscheint.

Diese Seite verwendet die Sammlung „ tech_articles “ aus dem Abschnitt „Erstellen eines StructArray-Feldes“. Die Sammlung enthält ein StructArray-Feld namens „ chunks “. Das Vektor-Unterfeld „ chunks[emb] “ ist für die Suche auf Elementebene mit einer regulären Vektormetrik indiziert.

Wie die Gruppierung auf StructArray angewendet wird

SuchmodusGruppierungsverhaltenVerhalten der Ergebnisse
„EmbeddingList“-SucheNicht unterstützt.Nicht zutreffend.
Suche auf ElementebeneWird durch Gruppierung nach dem Primärschlüssel unterstützt.Liefert höchstens ein Ergebnis pro übergeordneter Entität. Metadaten auf Elementebene bleiben erhalten, sodass der Index oder Offset des ausgewählten Elements zurückgegeben werden kann, wenn dieser über die API oder das SDK bereitgestellt wird.
Hybride SucheWird nur unterstützt, wenn alle Teilsuchen auf Vektorfelder auf Elementebene unter demselben StructArray-Feld abzielen.Teilsuchen auf Elementebene werden vor der endgültigen Ergebnisverarbeitung nach Primärschlüssel gruppiert.

Verwenden Sie die Gruppierung, wenn eine nicht gruppierte Suche auf Elementebene zu viele doppelte übergeordnete Entitäten zurückgibt. Wenn Sie jedes übereinstimmende Struct-Element als einzelnen Treffer erhalten möchten, verwenden Sie die einfache Vektorsuche mit StructArray ohne „ group_by_field “.

Bevor Sie beginnen

Bereiten Sie die Sammlung, die Daten und die Indizes vor, bevor Sie die gruppierte Suche ausführen.

VoraussetzungDetails
Vektor-Unterfeld auf ElementebeneVerwenden Sie ein StructArray-Vektor-Unterfeld wie beispielsweise „ chunks[emb] “, das mit einer regulären Vektormetrik indiziert ist.
Reguläre VektorabfrageVerwenden Sie einen regulären Abfragevektor, keinen „ EmbeddingList “.
Gruppierung nach PrimärschlüsselVerwenden Sie den Primärschlüssel der Sammlung als „ group_by_field “, z. B. „ doc_id “.
Keine BereichsparameterKombinieren Sie die Gruppierungssuche nicht mit Bereichssuchparametern wie radius oder range_filter.

Informationen zur Indexeinrichtung finden Sie unter „Index StructArray-Felder“.

Im folgenden Beispiel werden zunächst einzelne Chunks durchsucht, anschließend werden die Elementtreffer anhand des Primärschlüssels der übergeordneten Entität gruppiert.

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

Ohne Gruppierung kann dasselbe „ doc_id “ mehrfach erscheinen, wenn mehrere Chunks der Abfrage entsprechen. Mit „ group_by_field="doc_id" “ erscheint jede übergeordnete Entität höchstens einmal. Durch die Gruppierung bleiben Metadaten auf Elementebene erhalten, sodass das gruppierte Ergebnis weiterhin den ausgewählten Struct-Element-Index oder -Offset enthalten kann, sofern die API oder das SDK diesen bereitstellt.

Skalarfilter hinzufügen

Sie können die Gruppierungssuche mit der skalaren Filterung von `StructArray` kombinieren. Verwenden Sie ` element_filter `, wenn die skalare Bedingung einschränken soll, welche `Struct`-Elemente an der Vektorsuche auf Elementebene teilnehmen.

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

Das Prädikat der obersten Ebene wählt Kandidatenentitäten aus. Das Prädikat „ element_filter “ beschränkt die Vektorsuche auf Elementebene auf übereinstimmende Struct-Elemente. Die Gruppierung fasst dann die übereinstimmenden Elementtreffer anhand des Primärschlüssels zusammen.

Die hybride Gruppierung mit „StructArray“ ist eine Funktion auf Elementebene. Sie wird nur unterstützt, wenn alle Teilsuchen auf Vektorfelder auf Elementebene unter demselben „StructArray“-Feld abzielen. Verwenden Sie keine Anfragen auf „EmbeddingList“-Ebene in einer gruppierten hybriden „StructArray“-Suche.

Das folgende Beispiel geht davon aus, dass das StructArray-Feld „ chunks “ zwei Vektor-Unterfelder auf Elementebene enthält, „ chunks[emb] “ und „ chunks[code_emb] “, und dass beide mit regulären Vektormetriken indiziert sind.

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 diesem Beispiel zielen beide Unterabfragen auf Vektorfelder auf Elementebene unter demselben StructArray-Feld „ chunks “ ab. Eine Hybrid-Suche unterstützt keine Gruppierung auf Elementebene, wenn sie normale Vektorfelder, verschiedene StructArray-Felder oder Abfragen auf „EmbeddingList“-Ebene mischt.

Gruppierte Ergebnisse interpretieren

ErgebniselementBedeutung
idPrimärschlüssel der gruppierten übergeordneten Entität.
distance oder WertWert oder Abstand des ausgewählten Struct-Elements für diese übergeordnete Entität.
offsetNullbasierte Position des ausgewählten Struct-Elements bei der Rückgabe.
Wiederholte PrimärschlüsselBei einer Gruppierung nach dem Primärschlüssel nicht zu erwarten.
limitGilt für gruppierte Ergebnisse der übergeordneten Entität.

Einschränkungen

  • Die Gruppierungssuche gilt nur für die StructArray-Vektorsuche auf Elementebene. Die EmbeddingList-Suche und die hybride Suche auf EmbeddingList-Ebene unterstützen keine Gruppierung.

  • Verwenden Sie den Primärschlüssel als „ group_by_field “. Die Gruppierung auf StructArray-Ebene ist keine universelle Gruppierung nach beliebigen Skalarfeldern.

  • Kombinieren Sie die Gruppierungssuche nicht mit der Bereichssuche.

  • Verwenden Sie für die Gruppierungssuche keine „ EmbeddingList “-Abfrage oder eine „ MAX_SIM* “-Metrik.

  • Die hybride Gruppierung wird nur unterstützt, wenn alle Teilsuchen auf Vektorfelder auf Elementebene unter demselben StructArray-Feld abzielen.

  • Die hybride Gruppierung wird nicht unterstützt, wenn die hybride Suche ein normales Vektorfeld, ein anderes StructArray-Feld oder eine Abfrage auf EmbeddingList-Ebene einbezieht.

Häufige Fehler

  • Verwendung der Gruppierung mit „ chunks[emb_list_vector] “, das für die „EmbeddingList“-Suche vorgesehen ist.

  • Gruppierung nach einem Skalarfeld, das kein Primärschlüssel ist.

  • Gruppierung nach mehreren Feldern. Die StructArray-Gruppierung auf Elementebene unterstützt nur die Gruppierung nach Primärschlüsseln.

  • Die Erwartung, dass gruppierte Ergebnisse jedes übereinstimmende Struct-Element darstellen. Die Gruppierung liefert höchstens ein Ergebnis pro übergeordneter Entität.

  • Annahme, dass die gruppierte Suche auf Elementebene einen „ MAX_SIM* “-Score im Stil von „EmbeddingList“ neu berechnet. Die Gruppierung fasst Treffer auf Elementebene zusammen; sie ändert das Bewertungsmodell nicht.

  • Kombination von „ group_by_field “ mit „ radius “ oder „ range_filter “.

Nächste Schritte

  1. Um zunächst die ungegruppierte Suche auf Elementebene kennenzulernen, lesen Sie „Grundlegende Vektorsuche mit StructArray“.

  2. Um der gruppierten Suche skalare Filter hinzuzufügen, lesen Sie „Gefilterte Suche mit StructArray“.

  3. Um anstelle der Gruppierung Score- oder Distanzgrenzen zu verwenden, lesen Sie „Bereichssuche mit StructArray“.

  4. Um die Suchgrenzen von StructArray zu überprüfen, lesen Sie „StructArray-Grenzen“.