Gefilterte Suche mit StructArray
Verwenden Sie diese Seite, um die Vektorsuche in StructArray-Feldern um eine skalare Filterung zu erweitern. Die StructArray-Filterung erfolgt auf zwei Ebenen: Filter auf Zeilenebene wählen übergeordnete Entitäten aus, während Filter auf Elementebene festlegen, welche Struct-Elemente an der Vektorsuche auf Elementebene teilnehmen.
Diese Seite verwendet die Sammlung „ tech_articles “ aus dem Abschnitt „Erstellen eines StructArray-Feldes“. Die Sammlung enthält ein StructArray-Feld namens „ chunks “ mit skalaren Unterfeldern wie „ section “, „ page “, „ quality_score “ und „ has_code “ sowie Vektor-Unterfeldern für die Suche.
Wählen Sie einen Filtertyp
| Ziel | Verwendung | Verhalten des Ergebnisses |
|---|---|---|
Filtern nach einem Skalarfeld der obersten Ebene, z. B. category. | Regulärer Filterausdruck. | Wählt übergeordnete Entitäten vor oder während der Suche aus. |
| Beschränkt die Vektorsuche auf Elementebene auf Struct-Elemente, die den skalaren Bedingungen entsprechen. | element_filter. | Durchsucht nur übereinstimmende Struct-Elemente und kann Offsets der übereinstimmenden Elemente zurückgeben. |
| Wählt Entitäten danach aus, ob einige, alle oder eine bestimmte Anzahl von Struct-Elementen einem Prädikat entsprechen. | MATCH_ANY, MATCH_ALL, MATCH_LEAST, MATCH_MOST oder MATCH_EXACT. | Filterung auf Zeilenebene. Diese Operatoren geben selbst keine Offsets zurück. |
Auf dieser Seite wird erläutert, wie StructArray-Filter in Such-Workflows verwendet werden. Die vollständigen Syntaxregeln, unterstützte Prädikattypen und die Liste der nicht unterstützten Prädikate finden Sie unter „StructArray-Operatoren“.
Filtern nach Feldern der obersten Ebene
Verwenden Sie reguläre Filterausdrücke, wenn die Bedingung zur übergeordneten Entität gehört und nicht zu einem einzelnen Struct-Element. Dies funktioniert sowohl bei der EmbeddingList-Suche als auch bei der Suche auf Elementebene.
from pymilvus import MilvusClient
from pymilvus.client.embedding_list import EmbeddingList
client = MilvusClient(
uri="http://localhost:19530",
token="root:Milvus",
)
query = EmbeddingList()
query.add([0.12, 0.21, 0.32, 0.44])
query.add([0.18, 0.23, 0.29, 0.36])
results = client.search(
collection_name="tech_articles",
data=[query],
anns_field="chunks[emb_list_vector]",
filter='category == "search"',
limit=3,
output_fields=[
"doc_id",
"title",
"category",
"chunks[text]",
"chunks[section]",
],
)
Der obige Filter wählt nur Entitäten aus, deren Feld „ category “ auf oberster Ebene den Wert „ "search" “ hat. Er identifiziert kein einzelnes übereinstimmendes Struct-Element.
Filter für die Vektorsuche auf Elementebene
Verwenden Sie „ element_filter(structArrayField, predicate) “, wenn die skalaren Bedingungen für dasselbe Struct-Element gelten müssen, das an der Vektorsuche auf Elementebene beteiligt ist. Verwenden Sie innerhalb des Prädikats „ $[subfield] “, um auf skalare Unterfelder des aktuellen Struct-Elements zu verweisen.
query_vector = [0.19, 0.24, 0.30, 0.37]
filter_expr = (
'category == "search" && '
'element_filter(chunks, '
'$[section] == "index" && '
'$[quality_score] > 0.9 && '
'$[has_code] == true)'
)
results = client.search(
collection_name="tech_articles",
data=[query_vector],
anns_field="chunks[emb]",
filter=filter_expr,
limit=5,
output_fields=[
"doc_id",
"title",
"chunks[text]",
"chunks[section]",
"chunks[page]",
"chunks[quality_score]",
"chunks[has_code]",
],
)
for hits in results:
for hit in hits:
print(
"doc_id:", hit["id"],
"distance:", hit["distance"],
"offset:", hit.get("offset"),
"entity:", hit["entity"],
)
In diesem Beispiel wählt das Prädikat oberster Ebene „ category == "search" “ Kandidatenentitäten aus, und „ element_filter “ beschränkt die Vektorsuche auf Elementebene auf Blöcke, in denen „ section “, „ quality_score “ und „ has_code “ alle im selben Struct-Element übereinstimmen.
Warnung
Wenn Sie ein Prädikat der obersten Ebene mit „ element_filter “ kombinieren, platzieren Sie „ element_filter “ am Ende des Ausdrucks. Ein Filterausdruck darf nur ein „ element_filter “ enthalten, und Sie können „ element_filter “ oder „ MATCH_* “ nicht innerhalb eines anderen „StructArray“-Operators verschachteln.
Entitäten mit MATCH-Operatoren filtern
Verwenden Sie „ MATCH_* “-Operatoren, wenn der Filter anhand der Struct-Elemente entscheiden soll, ob eine übergeordnete Entität die Bedingungen erfüllt. Diese Operatoren sind Filter auf Zeilenebene: Sie wählen Entitäten aus, geben jedoch selbst keine Element-Offsets zurück.
| Operator | Verwenden Sie ihn, wenn | Beispiel |
|---|---|---|
MATCH_ANY | Mindestens ein Struct-Element muss das Prädikat erfüllen. | MATCH_ANY(chunks, $[section] == "index") |
MATCH_ALL | Alle Struct-Elemente müssen das Prädikat erfüllen. | MATCH_ALL(chunks, $[quality_score] > 0.5) |
MATCH_LEAST | Mindestens N -Struktur-Elemente müssen das Prädikat erfüllen. | MATCH_LEAST(chunks, $[has_code] == true, threshold=2) |
MATCH_MOST | Höchstens N Struct-Elemente müssen das Prädikat erfüllen. | MATCH_MOST(chunks, $[section] == "appendix", threshold=1) |
MATCH_EXACT | Genau N Struct-Elemente müssen das Prädikat erfüllen. | MATCH_EXACT(chunks, $[section] == "summary", threshold=1) |
filter_expr = (
'category == "search" && '
'MATCH_ANY(chunks, $[section] == "index" && $[quality_score] > 0.9)'
)
results = client.search(
collection_name="tech_articles",
data=[query],
anns_field="chunks[emb_list_vector]",
filter=filter_expr,
limit=3,
output_fields=[
"doc_id",
"title",
"category",
"chunks[text]",
"chunks[section]",
"chunks[quality_score]",
],
)
Verwenden Sie hier „ MATCH_ANY “, da das Suchergebnis von „EmbeddingList“ auf Entitätsebene erfolgt. Der Filter erfordert, dass mindestens ein Chunk in der Entität ein „ "index" “-Chunk mit hoher Qualität ist, das Suchergebnis selbst repräsentiert jedoch weiterhin die übergeordnete Entität.
Verwenden Sie Filter in der hybriden Suche
Wenden Sie in der hybriden Suche „StructArray“-Filter dort an, wo die Bedingung wirksam werden soll. Ein Filter auf oberster Ebene kann von der gesamten hybriden Suche gemeinsam genutzt werden. Ein „ element_filter “ sollte an die „StructArray“-Anfrage auf Elementebene angehängt werden, die Einschränkungen auf Elementebene erfordert.
from pymilvus import AnnSearchRequest, RRFRanker
query_vector = [0.19, 0.24, 0.30, 0.37]
title_req = AnnSearchRequest(
data=[query_vector],
anns_field="title_vector",
limit=10,
)
chunk_req = AnnSearchRequest(
data=[query_vector],
anns_field="chunks[emb]",
limit=10,
expr='element_filter(chunks, $[section] == "index" && $[quality_score] > 0.9)',
)
results = client.hybrid_search(
collection_name="tech_articles",
reqs=[title_req, chunk_req],
ranker=RRFRanker(),
filter='category == "search"',
limit=5,
output_fields=[
"doc_id",
"title",
"category",
"chunks[text]",
"chunks[section]",
"chunks[quality_score]",
],
)
Das Argument „ filter “ wendet die Entitätsbedingung der obersten Ebene an, während „ expr “ auf „ chunk_req “ nur die Vektorabfrage auf StructArray-Ebene einschränkt. Informationen zu unterstützten Kombinationen der hybriden Suche und versionsspezifischen Einschränkungen finden Sie unter „Hybride Suche mit StructArray“ und „StructArray-Einschränkungen“.
Zusammenfassung der Prädikatunterstützung
Verwenden Sie skalare Unterfelder in StructArray-Prädikaten. Vektor-Unterfelder sind keine Eingaben für skalare Prädikate.
| Unterfeldtyp | Typische Prädikatbeispiele |
|---|---|
BOOL | $[has_code] == true, !($[has_code] == true) |
| Ganzzahltypen | $[page] >= 2, $[page] in [1, 2, 3] |
FLOAT, DOUBLE | $[quality_score] > 0.9, 0.7 < $[quality_score] < 0.95 |
VARCHAR | $[section] == "index", $[text] like "range%" |
| Vektor-Teilfelder | Werden nicht als skalare Prädikate für „ $[...] “ unterstützt. Verwenden Sie stattdessen Vektor-Teilfelder über die Vektorsuche. |
Für nicht unterstützte Fälle wie JSON-Pfade, Array-Container-Funktionen, Textabgleichsfunktionen, Null-Prädikate auf ` $[...]`, Geometrie-Funktionen, `Timestamptz`-Ausdrücke und generische Funktionsaufrufe siehe „StructArray-Operatoren“.
Häufige Fehler
Verwendung von „
$[subfield]“ außerhalb von „element_filter“ oder „MATCH_*“.Verwendung von „
chunks.section“ anstelle der StructArray-Operatorsyntax wie beispielsweise „element_filter(chunks, $[section] == "index")“.Verwendung von „
element_filter“, wenn nur eine Filterung auf Zeilenebene erforderlich ist. Verwenden Sie stattdessen „MATCH_ANY“, wenn Sie lediglich Entitäten auswählen müssen.Die Erwartung, dass `
MATCH_*` Element-Offsets zurückgibt. Diese Operatoren wählen Entitäten aus und identifizieren selbst kein einzelnes übereinstimmendes Element.Das Schreiben von bloßen booleschen Prädikaten wie „
$[has_code]“. Verwenden Sie explizite Vergleiche wie „$[has_code] == true“.„
element_filter“ vor einem Prädikat der obersten Ebene im selben Filterausdruck platzieren.
Nächste Schritte
Um die vollständige StructArray-Filtersyntax nachzulesen, lesen Sie „StructArray-Operatoren“.
Um zunächst ungefilterte Vektorsuchen durchzuführen, lesen Sie „Grundlegende Vektorsuche mit StructArray“.
Informationen zum Erstellen von Skalarindizes für häufig verwendete StructArray-Filter finden Sie unter „StructArray-Felder indizieren“.
Informationen zu versionsspezifischen Filter- und Suchbeschränkungen finden Sie unter „StructArray-Beschränkungen“.