Agregasi PencarianCompatible with Milvus 3.0.x
Ketika seorang pembeli mencari “sepatu lari hitam untuk latihan harian,” pencarian approximate nearest neighbor (ANN) mengurutkan produk berdasarkan kemiripan vektor dan menghasilkan daftar Top-K yang datar. Hasilnya mungkin relevan tetapi berulang: dalam contoh di bawah ini, empat dari enam hasil pertama adalah produk Merek A, sedangkan Merek B dan Merek C masing-masing muncul satu kali.
Daftar datar tidak dapat secara langsung memberikan ringkasan yang berorientasi pada kelompok. Sebuah aplikasi mungkin perlu membandingkan merek berdasarkan jumlah kandidat yang disimpan atau harga rata-rata, memeriksa sejumlah kecil produk representatif dari setiap merek, atau mengorganisir hasil ke dalam beberapa tingkatan kelompok.
Agregasi Pencarian mengelompokkan kandidat ANN yang disimpan ke dalam bucket berdasarkan bidang skalar yang dipilih. Dalam contoh ini, setiap merek menjadi bucket tersendiri. Milvus dapat menghitung statistik untuk setiap bucket, mengurutkan bucket-bucket tersebut, dan melampirkan produk-produk yang representatif. Aplikasi mengonsumsi respons berbasis bucket ini melalui result.agg_buckets.
Hasil pencarian sepatu lari yang datar berubah menjadi sekumpulan kelompok merek yang dapat dibandingkan
Agregasi Pencarian tidak menjalankan agregasi koleksi penuh yang tepat. Keberadaan kelompok, jumlah, metrik, urutan, dan hasil yang representatif bergantung pada kandidat yang disimpan oleh ANN dan tahap pengelompokan.
Cara kerjanya
Kandidat ANN yang dikelompokkan berdasarkan kunci bucket dan dikembalikan bersama jumlah, metrik, serta hasil yang mewakili
Mengambil kandidat. Milvus menjalankan pencarian ANN untuk menemukan entitas yang paling dekat dengan vektor kueri. Tahap pengelompokan kemudian mempertahankan sejumlah kandidat yang dibatasi untuk setiap kunci komposit lengkap. Batas kandidat per kunci ini adalah yang terbesar
TopHits.sizedi mana pun dalam pohon agregasi, atau1ketika tidak ada tingkat yang mengonfigurasitop_hits.Membuat bucket.
SearchAggregation.fieldsmenentukan kunci bucket. Setiap kombinasi unik nilai bidang menghasilkan kunci terpisah. Pada gambar,fields=["brand"]menghasilkan kunci bucket(Brand A),(Brand B), dan(Brand C). Kandidat yang dipertahankan dengan kunci yang sama termasuk dalam bucket yang sama dan berkontribusi padacount-nya.SearchAggregation.sizemembatasi jumlah bucket yang dikembalikan oleh Milvus.Hitung dan kembalikan hasil. Setiap bucket yang dikembalikan berisi kuncinya dan jumlah kandidat yang dipertahankan. Milvus juga dapat menghitung metrik yang dikonfigurasi, mengurutkan bucket, mengembalikan entitas representatif, dan membangun bucket anak. Setiap
AggregationBucketdiresult.agg_bucketsmengeksposkey,count,metrics,hits, dansub_groups. Saat Search Aggregation diaktifkan, daftar hasil pencarian biasa kosong.
Dalam diagram, TopHits.size=4 menyediakan anggaran kandidat per kunci sebesar empat, sehingga empat kandidat Merek A yang dipertahankan menghasilkan count: 4. Kartu Merek A yang telah selesai hanya menampilkan dua dari empat hasil representatif yang dikembalikan agar gambar tetap ringkas.
Dengan " sub_aggregation", Milvus mengulangi langkah 2 dan 3 di dalam setiap bucket induk. Perubahan pada recall ANN atau anggaran kandidat per kunci dapat mengubah jumlah bucket, metrik, urutan, hasil pencarian, dan hasil bersarang.
Batasan
Sebelum menggunakan Search Aggregation, perhatikan batasan berikut:
Agregasi bersarang: Sebuah permintaan dapat berisi satu
SearchAggregationakar dan hingga tiga tingkatsub_aggregationbersarang, dengan total maksimal empat tingkat. Di seluruh tingkat, paling banyak 10 bidang dapat digunakan untuk membuat kunci bucket.Kolom yang digunakan untuk membuat kunci bucket:
SearchAggregation.fieldsmendukung kolom Boolean, integer,VARCHAR, danTIMESTAMPTZ. Fitur ini tidak mendukung kolomFLOAT,DOUBLE,ARRAY,JSON,GEOMETRY,TEXT, vektor, atau kolom dinamis.Bidang metrik:
countmenerima"*"atau bidang apa pun yang bukanJSONdan bukan bidang dinamis, serta mengabaikan nilaiNULLsaat bidang ditentukan.sumdanavgmenerima bidang bilangan bulat dan bilangan desimal.mindanmaxjuga menerima bidang string danTIMESTAMPTZ.Kolom penyortiran Top Hits:
TopHits.sortmendukung kolom Boolean, integer, floating-point, string, danTIMESTAMPTZyang dapat dibandingkan, serta_score. Kolom ini tidak mendukungARRAY,JSON,GEOMETRY, vektor, atau kolom dinamis.Anggaran kandidat: Nilai
TopHits.sizeterbesar di mana pun dalam pohon agregasi juga merupakan jumlah kandidat yang disimpan per kunci komposit lengkap. Jika tidak ada tingkat yang mengonfigurasitop_hits, Milvus menyimpan satu kandidat per kunci. Bucketcountdan metrik dihitung dari kandidat yang disimpan ini, sehingga mengubahTopHits.sizedapat mengubahnya.Bidang bucket yang dapat bernilai null: Nilai `
NULL` membentuk kunci bucket tersendiri. Untuk mengecualikan bucket null, tambahkan filter seperti `brand is not null` ke permintaan pencarian.Kolom yang diulang: Kolom yang sama tidak boleh muncul di lebih dari satu daftar
SearchAggregation.fields. Misalnya, jika agregasi akar menggunakanfields=["category"],sub_aggregationyang bersarang tidak boleh juga menggunakanfields=["category"].Kombinasi yang tidak didukung: Search Aggregation tidak dapat digabungkan dengan
offsetyang nilainya bukan nol, Search Iterators, Hybrid Search, Highlighter, atau Grouping Search. Nilaioffsettingkat atas berupa0setara dengan mengabaikan parameter tersebut. Dalam permintaan pencarian REST v2,searchAggregationdanidstidak dapat ditentukan secara bersamaan.Entri yang dikembalikan: Secara default, Milvus menolak permintaan Search Aggregation jika jumlah maksimum entri hasil yang dihitung melebihi 10.000. Ambang batas ini dikendalikan oleh
proxy.maxSearchAggregationResultEntries. Atur nilai konfigurasi menjadi0atau angka negatif untuk menonaktifkan pemeriksaan ini.Milvus menghitung batas maksimum ini sebagai berikut:
number of query vectors × product of the effective search_size at every aggregation level × largest TopHits.size at any levelUntuk perhitungan sisi server ini, nilai `
search_size` yang berlaku pada suatu level adalah `search_size` yang dikonfigurasi secara eksplisit, atau `size` pada level tersebut jika `search_size` diabaikan. API PyMilvus yang digunakan dalam panduan ini saat ini tidak mengekspos `search_size`, sehingga permintaan PyMilvus menggunakan `size` pada setiap level untuk perhitungan ini. Gunakan1untuk faktor terakhir jika tidak ada level yang mengonfigurasiTopHits. Misalnya, satu vektor kueri, 10 root bucket, lima child bucket per root bucket, dan dua hits per child bucket menghasilkan nilai maksimum yang dihitung sebesar:1 × 10 × 5 × 2 = 100
Gunakan Agregasi Pencarian
Pilih contoh berdasarkan tujuan yang ingin Anda capai:
| Buka | Deskripsi | Pengaturan utama |
|---|---|---|
| Bandingkan dan urutkan bucket | Hitung statistik per bucket untuk membandingkan bucket, lalu urutkan bucket yang ditampilkan berdasarkan metrik, jumlah, atau kunci. | fields, size, metrics, order |
| Tampilkan hasil representatif dari setiap bucket | Kembalikan sejumlah entitas terbatas dari setiap bucket dan urutkan entitas-entitas tersebut secara terpisah berdasarkan bidang skalar atau skor vektor. | top_hits, TopHits.size, TopHits.sort |
| Kelompokkan hasil pada beberapa tingkatan | Atur hasil ke dalam tingkatan bucket induk dan anak untuk menganalisis berbagai dimensi secara berurutan. | sub_aggregation |
Contoh di bawah ini menggunakan koleksi produk dengan bidang merek, kategori, warna, harga, dan peringkat. Semua nama merek, nama produk, harga, peringkat, dan hasil pencarian merupakan data contoh sintetis. Perluas bagian berikut untuk membuat koleksi dan mendefinisikan variabel pencarian bersama.
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": {},
}
Pengaturan di atas mengonfigurasi COSINE untuk indeks vektor dan parameter pencarian. Oleh karena itu, contoh-contoh selanjutnya menggunakan {"_score": "desc"} untuk menempatkan kesamaan kosinus yang lebih tinggi terlebih dahulu. Untuk metrik jarak seperti L2, gunakan {"_score": "asc"}.
Membandingkan dan mengurutkan bucket
Gunakan pola ini saat Anda perlu membandingkan kelompok entitas yang diambil menggunakan statistik yang dihitung dan mengontrol urutan pengembalian bucket. Dalam contoh ini, Milvus mengelompokkan produk yang diambil berdasarkan brand, menghitung metrik harga untuk setiap bucket merek, dan mengurutkan bucket berdasarkan harga rata-rata.
Jika tujuan Anda hanya untuk meningkatkan keragaman hasil dengan mengembalikan satu atau lebih entitas per nilai bidang, gunakan Pencarian Pengelompokan sebagai gantinya.
Konfigurasi berikut ini membuat hingga tiga bucket merek, menghitung metrik untuk setiap bucket, dan mengurutkan bucket berdasarkan harga rata-rata:
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"},
],
)
Berikan objek tersebut ke parameter ` search_aggregation ` dari ` 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,
)
Saat ` search_aggregation ` diatur, PyMilvus tidak mengembalikan entitas biasa dalam ` result[0]`. Baca respons bucket dari ` result.agg_buckets[0] ` sebagai gantinya. Parameter ` output_fields ` mengontrol bidang skalar mana yang muncul dalam setiap pemetaan ` AggregationHit.fields ` yang dikembalikan; Milvus tetap dapat menggunakan bidang sumber metrik dan bidang pengurutan yang tidak tercantum dalam ` output_fields`.
Output berikut diambil dari permintaan di atas dan diserialisasikan sebagai JSON agar mudah dibaca. PyMilvus mengembalikan objek ` AggregationBucket `, bukan JSON. Nilai ` key ` selalu berupa daftar terurut dari komponen kunci, bahkan ketika ` fields ` hanya berisi satu bidang. Hal ini menjaga urutan bidang untuk kunci gabungan.
[
{
"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": []
}
]
Untuk vektor kueri tunggal dalam panduan ini, bacalah bucket tingkat atas yang dikembalikan dari ` result.agg_buckets[0]`. Setiap bucket menampilkan komponen kunci yang terurut, `retained-candidate` (` count`), `calculated` (` metrics`), `representative` (` hits`), dan bucket bersarang di ` sub_groups`.
Baca konfigurasi sebagai berikut:
| Pengaturan | Apa yang dikendalikan | Dalam contoh ini |
|---|---|---|
fields | Bagaimana Milvus membuat kunci bucket | Membuat satu bucket untuk setiap nilai brand yang berbeda. |
size | Jumlah maksimum bucket yang dikembalikan | Mengembalikan hingga tiga bucket merek. |
metrics | Statistik yang dihitung untuk setiap bucket | Menghitung jumlah produk, harga rata-rata, dan harga minimum. |
order | Cara Milvus mengurutkan bucket yang dikembalikan | Mengurutkan berdasarkan harga rata-rata, kemudian menggunakan kunci bucket untuk menentukan urutan jika terjadi kesamaan. |
Milvus mengabaikan " limit " ketika " search_aggregation " diatur. Gunakan nilai " SearchAggregation.size " akar untuk mengontrol jumlah bucket tingkat atas.
Dengan pengaturan ini, Milvus mengembalikan bucket Merek B, Merek A, dan Merek C dalam urutan harga rata-rata ( avg_price ) menurun. Kriteria ` _key ` hanya berlaku ketika bucket memiliki harga rata-rata yang sama. Karena konfigurasi ini tidak mendefinisikan ` top_hits`, daftar ` hits ` setiap bucket kosong dan anggaran kandidat per kunci adalah ` 1`. Oleh karena itu, jumlah dan metrik yang ditampilkan menggambarkan satu kandidat yang dipertahankan per merek. Konfigurasikan ` top_hits ` dengan ` TopHits.size ` yang lebih besar ketika agregasi memerlukan jendela metrik per kunci yang lebih luas.
Setiap entri SearchAggregation.metrics memetakan alias yang ditentukan pengguna ke {operation: source}:
| Sumber | Operasi yang didukung | Perilaku |
|---|---|---|
Setiap bidang yang bukanJSON dan bukan bidang dinamis | count | Menghitung kandidat yang dipertahankan yang bidang sumbernya bukan NULL. |
| Bidang bilangan bulat atau bilangan pecahan | sum, ` avg`, ` min`, max | Menghitung nilai yang dipertahankan yang tidak null. |
Bidang string atau TIMESTAMPTZ | min, max | Memilih nilai yang disimpan non-null minimum atau maksimum. |
"*" | count | Menghitung setiap kandidat yang dipertahankan dalam bucket. Hasilnya sesuai dengan bucket.count. |
_score | sum, avg, min, max | Menghitung nilai kesamaan atau jarak ANN untuk kandidat yang dipertahankan. |
SearchAggregation.order menerima kunci-kunci berikut:
| Kunci urutan | Arti |
|---|---|
| Alias metrik | Mengurutkan berdasarkan nilai yang dihitung dalam metrics pada tingkat agregasi yang sama, seperti avg_price. |
_count | Mengurutkan berdasarkan jumlah kandidat yang disimpan di setiap bucket. |
_key | Mengurutkan berdasarkan kunci bucket, bukan berdasarkan bidang koleksi bernama _key. |
Setiap entri ` order ` memetakan kunci ke ` "asc" ` atau ` "desc"`. Milvus mengevaluasi entri-entri tersebut dari yang pertama hingga yang terakhir. Jika Anda mengabaikan ` order`, Milvus mempertahankan urutan penemuan bucket dari himpunan kandidat yang dipertahankan.
Untuk mengurutkan bucket berdasarkan kualitas kecocokan vektor, pertama-tama hitung metrik tingkat bucket dari _score, lalu gunakan alias metrik tersebut di order. Anda tidak dapat menggunakan _score secara langsung sebagai kunci urutan bucket karena setiap bucket dapat berisi beberapa skor entitas. Misalnya, dengan COSINE atau IP:
aggregation = SearchAggregation(
fields=["brand"],
size=3,
metrics={"max_score": {"max": "_score"}},
order=[{"max_score": "desc"}],
)
Dengan L2, hitung nilai _score terendah dan urutkan alias metrik secara ascending sehingga bucket dengan jarak terendah muncul terlebih dahulu.
Untuk membuat kunci bucket gabungan, masukkan beberapa nama bidang dalam daftar yang sama:
aggregation = SearchAggregation(
# Combine brand and color to form a composite bucket key.
fields=["brand", "color"],
size=6,
)
Konfigurasi ini dapat menghasilkan kunci seperti (Brand A, black), (Brand A, blue), dan (Brand B, white). Dua entitas hanya berbagi bucket jika kedua nilainya cocok. Milvus mempertahankan urutan daftar, sehingga brand menjadi komponen kunci pertama dan color menjadi yang kedua. Saat _key digunakan dalam order, Milvus membandingkan komponen kunci gabungan dalam urutan yang sama. Masukkan beberapa string dalam satu daftar datar; daftar bersarang tidak didukung.
size=6 adalah jumlah maksimum bucket gabungan yang dikembalikan pada tingkat agregasi ini. Data contoh berisi lima kombinasi merek-warna yang berbeda, sehingga kelimanya dapat dikembalikan. Dalam batas entri yang dikembalikan, permintaan ini menyumbang 1 query vector × 6 buckets × 1 = 6 entri hasil yang dikonfigurasi.
Beberapa bidang dalam satu daftar ` SearchAggregation.fields ` membentuk kunci bucket komposit pada tingkat agregasi tersebut. Untuk membuat hierarki bucket induk-anak, gunakan agregasi bersarang.
Contoh-contoh berikut mendefinisikan ulang ` aggregation`. Berikan objek yang telah diperbarui ke parameter ` search_aggregation ` yang sama dan jalankan kembali panggilan pencarian.
Tampilkan hasil representatif dari setiap bucket
Sertakan entitas representatif saat aplikasi perlu menampilkan produk aktual dari setiap bucket. Dalam contoh ini, Milvus mengembalikan hingga dua produk dari setiap bucket merek, diurutkan berdasarkan peringkat dan kemudian berdasarkan skor vektor.
Konfigurasikan ` TopHits ` sebagai berikut:
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"},
],
),
)
Bucket Merek A berikut ini diambil dari permintaan di atas dan diserialisasikan sebagai JSON agar mudah dibaca.
{
"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 | Tujuan |
|---|---|
top_hits | Opsional. Mengonfigurasi entitas representatif untuk tingkat agregasi ini. Jika diabaikan, ` bucket.hits ` akan kosong dan anggaran kandidat per kunci secara default ditetapkan menjadi satu. |
TopHits.size | Mengembalikan hingga dua entitas representatif dari setiap bucket yang dipilih dan menetapkan anggaran kandidat per-kunci menjadi dua untuk seluruh pohon agregasi. |
TopHits.sort | Mengurutkan entitas di dalam setiap bucket menggunakan kriteria yang tercantum. |
Konfigurasikan ` top_hits ` ketika aplikasi memerlukan entitas representatif atau ketika hitungan dan metrik memerlukan jendela kandidat per-kunci yang lebih luas. Nilai ` TopHits.size ` yang lebih besar meningkatkan baik anggaran kandidat maupun perhitungan entri maksimum yang dikembalikan di `Limits`.
SearchAggregation.order mengurutkan bucket, sedangkan " TopHits.sort " mengurutkan entitas yang dipertahankan di dalam setiap bucket. Urutan pengurutan tidak mengubah kandidat mana yang dipertahankan untuk " count " dan metrik. " TopHits.sort " menerima nama bidang skalar yang dapat dibandingkan yang didukung serta bidang bawaan " _score ", yang mewakili kemiripan atau jarak ANN. Milvus mengevaluasi entri " sort " dari yang pertama hingga yang terakhir. Dalam contoh ini, produk diurutkan berdasarkan rating dari nilai tertinggi ke terendah dan menggunakan _score hanya ketika dua penilaian sama. Karena pengaturan menggunakan COSINE, urutan menurun _score menempatkan produk yang lebih serupa di urutan pertama.
Kolom yang digunakan oleh metrics atau TopHits.sort tidak harus muncul di output_fields. Milvus mengambil kolom-kolom tersebut secara internal, tetapi hanya kolom yang secara eksplisit tercantum di output_fields yang disertakan dalam pemetaan fields setiap hasil yang dikembalikan. Kunci utama dan skor vektor tetap tersedia melalui AggregationHit.pk dan AggregationHit.score.
Setiap hasil yang dikembalikan AggregationHit menampilkan kunci utamanya di pk, skor vektor di score, dan bidang keluaran yang diminta di fields.
Mengelompokkan hasil pada beberapa tingkatan
Gunakan agregasi bersarang saat Anda memerlukan satu tingkat bucket di dalam tingkat lainnya. Dalam contoh ini, Milvus membuat bucket kategori terlebih dahulu, lalu membuat bucket merek di dalam setiap kategori.
Agregasi anak hanya menerima entitas yang ditugaskan ke bucket induknya. fields mengontrol kunci bucket di setiap tingkat agregasi, sedangkan sub_aggregation membuat hierarki induk-anak.
Konfigurasi di bawah ini membuat bucket kategori dengan kunci (running_shoes). Di dalam bucket induk tersebut, agregasi anak membuat bucket merek terpisah dengan kunci seperti (Brand A), (Brand B), dan (Brand C).
Parent bucket key:
(running_shoes)
Child bucket keys:
├── (Brand A)
├── (Brand B)
└── (Brand C)
Setiap tingkatan dapat menggunakan beberapa bidang secara independen. Misalnya, penggunaan fields=["brand", "color"] dalam agregasi anak akan menghasilkan kunci anak gabungan seperti (Brand A, black).
Konfigurasi berikut mengimplementasikan hierarki ini:
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"}],
),
),
)
Kutipan serialisasi berikut menunjukkan bucket induk running_shoes dan bucket anak Brand B-nya. Bucket anak Brand A dan Brand C dihilangkan demi singkatnya.
{
"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": []
}
]
}
Hasil yang ditampilkan mewakili jalur bucket (running_shoes) → (Brand B), bukan kunci bucket komposit tunggal (running_shoes, Brand B).
Milvus pertama-tama memilih hingga dua bucket kategori, diurutkan berdasarkan product_count. Selanjutnya, Milvus menjalankan sub_aggregation secara independen di dalam setiap kategori yang dipilih dan mengembalikan hingga tiga bucket merek, diurutkan berdasarkan avg_rating.
Pada keluaran di atas:
- Bucket akar `
running_shoes` berisi empat kandidat yang dipertahankan di seluruh kunci komposit anaknya. Kunci `metrics`-nya berisi nilai `avg_price` dan `product_count` tingkat akar. - Daftar
sub_groupsbucket akar berisi bucket merek anak. Bucket Merek B yang ditampilkan berisi satu kandidat yang dipertahankan serta nilaiavg_ratingdanbrand_countmiliknya sendiri. - Daftar
hitspada bucket akar kosong karena agregasi akar tidak mengonfigurasitop_hits. Bucket anak Merek B berisi hit representatif karenatop_hitsdikonfigurasi disub_aggregation.
FAQ
Seberapa akuratkah jumlah bucket dan metriknya?
Agregasi Pencarian merangkum kandidat ANN yang dipertahankan. Agregasi ini tidak menjalankan agregasi koleksi penuh.
Retensi kandidat memiliki dua tahap perkiraan. Pencarian ANN dapat mengabaikan entitas koleksi yang relevan, dan tahap pengelompokan menyimpan paling banyak kandidat TopHits.size terbesar untuk setiap kunci komposit lengkap. Jika tidak ada tingkat yang mengonfigurasi top_hits, batas per kunci ini adalah satu.
Misalnya, anggaplah sebuah koleksi berisi 5.000 produk Merek A dan banyak di antaranya relevan dengan kueri vektor. Jika agregasi menggunakan ` TopHits(size=4)`, bucket Merek A dapat mempertahankan paling banyak empat kandidat untuk satu kunci komposit lengkap. ` count ` dan metriknya menggambarkan kandidat-kandidat yang dipertahankan tersebut, bukan semua produk Merek A yang relevan dan bukan semua 5.000 entitas koleksi.
Perkiraan menjadi sangat penting ketika ` order ` menggunakan alias metrik. Perubahan pada recall pencarian dapat mengubah nilai metrik dan karenanya mengubah bucket mana yang sesuai dengan ` SearchAggregation.size`. Agregasi bersarang dapat memperkuat efek ini karena setiap tingkat anak beroperasi pada entitas yang tersedia di bucket induknya.
Jika Anda memerlukan statistik yang tepat untuk setiap entitas yang cocok, gunakan alur kerja agregasi kueri eksak alih-alih Agregasi Pencarian.
Apa perbedaan antara Search Aggregation dan Grouping Search?
Pilihlah berdasarkan bentuk hasil utama aplikasi:
| Kebutuhan utama | Pilihan | Respons yang akan digunakan |
|---|---|---|
| Mengembalikan daftar entitas yang diurutkan secara standar dengan lebih sedikit nilai berulang dalam bidang pengelompokan | Pencarian Pengelompokan | Hasil pencarian datar untuk setiap vektor kueri |
| Periksa atau bandingkan grup sebagai bucket, dengan kunci, jumlah, metrik, urutan, hasil yang representatif, atau bucket anak | Agregasi Pencarian | AggregationBucket objek dalam result.agg_buckets |
Bahkan ketika Agregasi Pencarian dikonfigurasi dengan opsi " top_hits", respons utamanya tetap berupa pohon bucket. Pencarian Berkelompok tetap berguna ketika aplikasi sudah memproses hasil pencarian biasa dan terutama menginginkan keragaman hasil.
API-API ini saling eksklusif. PyMilvus memicu pengecualian " ParamError " ketika " search_aggregation " digabungkan dengan " group_by_field " atau " group_by_fields " dalam permintaan yang sama.