Pencarian Tersaring dengan StructArray

Gunakan halaman ini untuk menambahkan penyaringan skalar ke pencarian vektor pada bidang StructArray. Penyaringan StructArray memiliki dua tingkatan: penyaring tingkat baris memilih entitas induk, sedangkan penyaring tingkat elemen membatasi elemen Struct mana yang ikut serta dalam pencarian vektor tingkat elemen.

Halaman ini menggunakan koleksi " tech_articles " dari "Create a StructArray Field". Koleksi tersebut memiliki bidang StructArray bernama " chunks", dengan subbidang skalar seperti " section", " page", " quality_score", dan " has_code", serta subbidang vektor untuk pencarian.

Pilih jenis filter

TujuanPenggunaanPerilaku hasil
Saring berdasarkan bidang skalar tingkat atas, seperti category.Ekspresi filter biasa.Memilih entitas induk sebelum atau selama pencarian.
Membatasi pencarian vektor tingkat elemen ke elemen Struct yang sesuai dengan kondisi skalar.element_filter.Hanya mencari elemen Struct yang cocok dan dapat mengembalikan offset elemen yang cocok.
Memilih entitas berdasarkan apakah ada, semua, atau sejumlah tertentu elemen Struct yang sesuai dengan predikat.MATCH_ANY, MATCH_ALL, MATCH_LEAST, MATCH_MOST, atau MATCH_EXACT.Penyaringan tingkat baris. Operator-operator ini tidak mengembalikan offset secara langsung.

Halaman ini menjelaskan cara menggunakan filter StructArray dalam alur kerja pencarian. Untuk aturan sintaks lengkap, jenis predikat yang didukung, dan matriks predikat yang tidak didukung, lihat Operator StructArray.

Penyaringan berdasarkan bidang tingkat atas

Gunakan ekspresi filter biasa jika kondisi tersebut berlaku untuk entitas induk, bukan untuk elemen Struct individu. Ini berfungsi baik dengan pencarian EmbeddingList maupun pencarian tingkat elemen.

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

Filter di atas hanya memilih entitas yang bidang tingkat atasnya ( category ) adalah "search". Filter ini tidak mengidentifikasi satu elemen Struct yang cocok.

Gunakan ` element_filter(structArrayField, predicate) ` ketika kondisi skalar harus diterapkan pada elemen Struct yang sama yang berpartisipasi dalam pencarian vektor tingkat elemen. Di dalam predikat, gunakan ` $[subfield] ` untuk merujuk pada subbidang skalar dari elemen Struct saat ini.

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

Dalam contoh ini, predikat tingkat atas ` category == "search" ` memilih entitas kandidat, dan ` element_filter ` membatasi pencarian vektor tingkat elemen pada potongan di mana ` section`, ` quality_score`, dan ` has_code ` semuanya cocok dalam elemen Struct yang sama.

Peringatan

Saat Anda menggabungkan predikat tingkat atas dengan element_filter, letakkan element_filter di akhir ekspresi. Ekspresi filter hanya dapat berisi satu element_filter, dan Anda tidak dapat menyematkan element_filter atau MATCH_* di dalam operator StructArray lainnya.

Menyaring entitas dengan operator MATCH

Gunakan operator MATCH_* ketika filter harus menentukan apakah entitas induk memenuhi syarat berdasarkan elemen Struct-nya. Operator ini merupakan filter tingkat baris: mereka memilih entitas, tetapi tidak mengembalikan offset elemen secara langsung.

OperatorGunakan saatContoh
MATCH_ANYSetidaknya satu elemen Struct harus memenuhi predikat.MATCH_ANY(chunks, $[section] == "index")
MATCH_ALLSemua elemen Struct harus memenuhi predikat.MATCH_ALL(chunks, $[quality_score] > 0.5)
MATCH_LEASTSetidaknya N elemen Struct harus memenuhi predikat tersebut.MATCH_LEAST(chunks, $[has_code] == true, threshold=2)
MATCH_MOSTPaling banyak N elemen Struct harus memenuhi predikat tersebut.MATCH_MOST(chunks, $[section] == "appendix", threshold=1)
MATCH_EXACTTepat N elemen Struct harus memenuhi predikat.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]",
    ],
)

Gunakan ` MATCH_ANY ` di sini karena hasil pencarian `EmbeddingList` berada pada tingkat entitas. Filter ini mensyaratkan setidaknya satu chunk dalam entitas tersebut merupakan chunk ` "index" ` dengan kualitas tinggi, namun hasil pencarian itu sendiri tetap mewakili entitas induk.

Dalam pencarian hibrida, terapkan filter StructArray di mana kondisi tersebut harus berlaku. Filter tingkat atas dapat digunakan bersama oleh seluruh pencarian hibrida. element_filter harus dilampirkan ke permintaan tingkat elemen StructArray yang memerlukan batasan tingkat elemen.

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

Argumen ` filter ` menerapkan kondisi entitas tingkat atas, sedangkan ` expr ` pada ` chunk_req ` hanya membatasi permintaan vektor tingkat elemen StructArray. Untuk kombinasi pencarian hibrida yang didukung dan batasan versi tertentu, lihat Pencarian Hibrida dengan StructArray dan Batasan StructArray.

Ringkasan dukungan predikat

Gunakan subbidang skalar dalam predikat StructArray. Subbidang vektor bukanlah masukan predikat skalar.

Jenis subbidangContoh predikat umum
BOOL$[has_code] == true, !($[has_code] == true)
Tipe bilangan bulat$[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%"
Subbidang vektorTidak didukung sebagai masukan predikat skalar $[...]. Gunakan subbidang vektor melalui pencarian vektor sebagai gantinya.

Untuk kasus yang tidak didukung seperti jalur JSON, fungsi wadah array, fungsi pencocokan teks, predikat null pada $[...], fungsi Geometri, ekspresi Timestamptz, dan panggilan fungsi generik, lihat Operator StructArray.

Kesalahan umum

  • Menggunak $[subfield] di luar element_filter atau MATCH_*.

  • Menggunakan chunks.section alih-alih sintaks operator StructArray seperti element_filter(chunks, $[section] == "index").

  • Menggunakan element_filter saat Anda hanya memerlukan penyaringan tingkat baris. Gunakan MATCH_ANY sebagai gantinya jika Anda hanya perlu memilih entitas.

  • Mengharapkan ` MATCH_* ` mengembalikan offset elemen. Operator-operator ini memilih entitas dan tidak mengidentifikasi satu elemen yang cocok secara otomatis.

  • Menulis predikat boolean tanpa operator, seperti $[has_code]. Gunakan perbandingan eksplisit seperti $[has_code] == true.

  • Menempatkan ` element_filter ` sebelum predikat tingkat atas dalam ekspresi filter yang sama.

Langkah selanjutnya

  1. Untuk meninjau sintaks filter StructArray secara lengkap, baca StructArray Operators.

  2. Untuk menjalankan pencarian vektor tanpa filter terlebih dahulu, baca Pencarian Vektor Dasar dengan StructArray.

  3. Untuk membuat indeks skalar untuk filter StructArray yang sering digunakan, baca Indeks Bidang StructArray.

  4. Untuk memeriksa batasan filter dan pencarian yang spesifik untuk versi tertentu, baca Batasan StructArray.