Ricerca filtrata con StructArray
Utilizzare questa pagina per aggiungere filtri scalari alla ricerca vettoriale sui campi StructArray. Il filtraggio StructArray prevede due livelli: i filtri a livello di riga selezionano le entità padre, mentre i filtri a livello di elemento limitano quali elementi Struct partecipano alla ricerca vettoriale a livello di elemento.
Questa pagina utilizza la raccolta " tech_articles " descritta in "Creazione di un campo StructArray". La raccolta presenta un campo StructArray denominato " chunks", con sottocampi scalari quali " section", " page", " quality_score" e " has_code", oltre a sottocampi vettoriali per la ricerca.
Scegli un tipo di filtro
| Obiettivo | Utilizzo | Comportamento del risultato |
|---|---|---|
Filtra in base a un campo scalare di primo livello, come category. | Espressione di filtro regolare. | Seleziona le entità padre prima o durante la ricerca. |
| Limita la ricerca vettoriale a livello di elemento agli elementi Struct che soddisfano le condizioni scalari. | element_filter. | Cerca solo gli elementi Struct corrispondenti e può restituire gli offset degli elementi trovati. |
| Seleziona le entità in base al fatto che uno, tutti o un numero specifico di elementi Struct soddisfino un predicato. | MATCH_ANY, MATCH_ALL, MATCH_LEAST, MATCH_MOST o MATCH_EXACT. | Filtraggio a livello di riga. Questi operatori non restituiscono offset di per sé. |
Questa pagina spiega come utilizzare i filtri StructArray nei flussi di lavoro di ricerca. Per le regole sintattiche complete, i tipi di predicato supportati e la matrice dei predicati non supportati, consultare Operatori StructArray.
Filtraggio in base ai campi di primo livello
Utilizzare espressioni di filtro regolari quando la condizione riguarda l’entità padre, non un singolo elemento Struct. Ciò funziona sia con la ricerca EmbeddingList che con la ricerca a livello di elemento.
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]",
],
)
Il filtro sopra riportato seleziona solo le entità il cui campo di primo livello category è "search". Non identifica un singolo elemento Struct corrispondente.
Filtraggio della ricerca vettoriale a livello di elemento
Utilizzare ` element_filter(structArrayField, predicate) ` quando le condizioni scalari devono applicarsi allo stesso elemento Struct che partecipa alla ricerca vettoriale a livello di elemento. All’interno del predicato, utilizzare ` $[subfield] ` per fare riferimento ai sottocampi scalari dell’elemento Struct corrente.
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 questo esempio, il predicato di primo livello ` category == "search" ` seleziona le entità candidate, mentre ` element_filter ` limita la ricerca vettoriale a livello di elemento ai blocchi in cui ` section`, ` quality_score` e ` has_code ` corrispondono tutti nello stesso elemento Struct.
Avviso
Quando si combina un predicato di primo livello con element_filter, posizionare element_filter alla fine dell’espressione. Un’espressione di filtro può contenere un solo element_filter e non è possibile annidare element_filter o MATCH_* all’interno di un altro operatore StructArray.
Filtrare le entità con gli operatori MATCH
Utilizzare gli operatori MATCH_* quando il filtro deve decidere se un'entità padre soddisfa i requisiti in base ai propri elementi Struct. Questi operatori sono filtri a livello di riga: selezionano le entità, ma non restituiscono di per sé gli offset degli elementi.
| Operatore | Utilizzarlo quando | Esempio |
|---|---|---|
MATCH_ANY | Almeno un elemento Struct deve soddisfare il predicato. | MATCH_ANY(chunks, $[section] == "index") |
MATCH_ALL | Tutti gli elementi Struct devono soddisfare il predicato. | MATCH_ALL(chunks, $[quality_score] > 0.5) |
MATCH_LEAST | Almeno N elementi della struttura devono soddisfare il predicato. | MATCH_LEAST(chunks, $[has_code] == true, threshold=2) |
MATCH_MOST | Al massimo N elementi della struttura devono soddisfare il predicato. | MATCH_MOST(chunks, $[section] == "appendix", threshold=1) |
MATCH_EXACT | Esattamen N i elementi Struct devono soddisfare il predicato. | 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]",
],
)
Utilizzare " MATCH_ANY " in questo caso poiché il risultato della ricerca EmbeddingList è a livello di entità. Il filtro richiede che almeno un chunk nell'entità sia un chunk " "index" " di alta qualità, ma il risultato della ricerca stesso rappresenta comunque l'entità padre.
Utilizzo dei filtri nella ricerca ibrida
Nella ricerca ibrida, applicare i filtri StructArray dove la condizione deve avere effetto. Un filtro di primo livello può essere condiviso dall’intera ricerca ibrida. Un element_filter dovrebbe essere associato alla richiesta a livello di elemento StructArray che necessita di vincoli a livello di elemento.
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]",
],
)
L'argomento ` filter ` applica la condizione dell'entità di primo livello, mentre ` expr ` su ` chunk_req ` limita solo la richiesta vettoriale a livello di elemento di StructArray. Per le combinazioni di ricerca ibrida supportate e i limiti specifici per versione, consultare Ricerca ibrida con StructArray e Limiti di StructArray.
Riepilogo del supporto dei predicati
Utilizzare sottocampi scalari nei predicati StructArray. I sottocampi vettoriali non sono input per i predicati scalari.
| Tipo di sottocampo | Esempi tipici di predicati |
|---|---|
BOOL | $[has_code] == true, !($[has_code] == true) |
| Tipi interi | $[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%" |
| Sottocampi vettoriali | Non supportati come input per i predicati scalari di tipo $[...]. Utilizzare invece i sottocampi vettoriali tramite la ricerca vettoriale. |
Per i casi non supportati, quali percorsi JSON, funzioni relative ai contenitori array, funzioni di corrispondenza testuale, predicati null su $[...], funzioni geometriche, espressioni Timestamptz e chiamate a funzioni generiche, consultare Operatori StructArray.
Errori comuni
Utilizzo di `
$[subfield]` al di fuori di `element_filter` o `MATCH_*`.Utilizzo di `
chunks.section` al posto della sintassi degli operatori StructArray, come ad esempio `element_filter(chunks, $[section] == "index")`.Utilizzo di
element_filterquando è necessario solo un filtro a livello di riga. Utilizzare inveceMATCH_ANYse è necessario solo selezionare entità.Aspettarsi che `
MATCH_*` restituisca gli offset degli elementi. Questi operatori selezionano le entità e non identificano di per sé un singolo elemento corrispondente.Scrivere predicati booleani semplici come
$[has_code]. Utilizzare confronti espliciti come$[has_code] == true.Inserire `
element_filter` prima di un predicato di primo livello nella stessa espressione di filtro.
Prossimi passi
Per consultare la sintassi completa dei filtri StructArray, leggere Operatori StructArray.
Per eseguire prima ricerche vettoriali non filtrate, leggere Ricerca vettoriale di base con StructArray.
Per creare indici scalari per i filtri StructArray utilizzati di frequente, consultare la sezione " Indice dei campi StructArray".
Per verificare i limiti di filtro e ricerca specifici per versione, consultare Limiti di StructArray.