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.

A flat running-shoe search result becomes a set of comparable brand 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

ANN candidates grouped by bucket keys and returned with counts, metrics, and representative hits Kandidat ANN yang dikelompokkan berdasarkan kunci bucket dan dikembalikan bersama jumlah, metrik, serta hasil yang mewakili

  1. 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.size di mana pun dalam pohon agregasi, atau 1 ketika tidak ada tingkat yang mengonfigurasi top_hits.

  2. Membuat bucket. SearchAggregation.fields menentukan 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 pada count-nya. SearchAggregation.size membatasi jumlah bucket yang dikembalikan oleh Milvus.

  3. 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 AggregationBucket di result.agg_buckets mengekspos key, count, metrics, hits, dan sub_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 SearchAggregation akar dan hingga tiga tingkat sub_aggregation bersarang, 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.fields mendukung kolom Boolean, integer, VARCHAR, dan TIMESTAMPTZ. Fitur ini tidak mendukung kolom FLOAT, DOUBLE, ARRAY, JSON, GEOMETRY, TEXT, vektor, atau kolom dinamis.

  • Bidang metrik: count menerima "*" atau bidang apa pun yang bukanJSON dan bukan bidang dinamis, serta mengabaikan nilai NULL saat bidang ditentukan. sum dan avg menerima bidang bilangan bulat dan bilangan desimal. min dan max juga menerima bidang string dan TIMESTAMPTZ.

  • Kolom penyortiran Top Hits: TopHits.sort mendukung kolom Boolean, integer, floating-point, string, dan TIMESTAMPTZ yang dapat dibandingkan, serta _score. Kolom ini tidak mendukung ARRAY, JSON, GEOMETRY, vektor, atau kolom dinamis.

  • Anggaran kandidat: Nilai TopHits.size terbesar di mana pun dalam pohon agregasi juga merupakan jumlah kandidat yang disimpan per kunci komposit lengkap. Jika tidak ada tingkat yang mengonfigurasi top_hits, Milvus menyimpan satu kandidat per kunci. Bucket count dan metrik dihitung dari kandidat yang disimpan ini, sehingga mengubah TopHits.size dapat 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 menggunakan fields=["category"], sub_aggregation yang bersarang tidak boleh juga menggunakan fields=["category"].

  • Kombinasi yang tidak didukung: Search Aggregation tidak dapat digabungkan dengan offset yang nilainya bukan nol, Search Iterators, Hybrid Search, Highlighter, atau Grouping Search. Nilai offset tingkat atas berupa 0 setara dengan mengabaikan parameter tersebut. Dalam permintaan pencarian REST v2, searchAggregation dan ids tidak 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 menjadi 0 atau 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 level

    Untuk 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. Gunakan 1 untuk faktor terakhir jika tidak ada level yang mengonfigurasi TopHits. 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:

BukaDeskripsiPengaturan utama
Bandingkan dan urutkan bucketHitung 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 bucketKembalikan 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 tingkatanAtur 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.

Siapkan koleksi contoh

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`.

Lihat contoh keluaran bucket

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:

PengaturanApa yang dikendalikanDalam contoh ini
fieldsBagaimana Milvus membuat kunci bucketMembuat satu bucket untuk setiap nilai brand yang berbeda.
sizeJumlah maksimum bucket yang dikembalikanMengembalikan hingga tiga bucket merek.
metricsStatistik yang dihitung untuk setiap bucketMenghitung jumlah produk, harga rata-rata, dan harga minimum.
orderCara Milvus mengurutkan bucket yang dikembalikanMengurutkan 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.

Aturan metrik dan urutan

Setiap entri SearchAggregation.metrics memetakan alias yang ditentukan pengguna ke {operation: source}:

SumberOperasi yang didukungPerilaku
Setiap bidang yang bukanJSON dan bukan bidang dinamiscountMenghitung kandidat yang dipertahankan yang bidang sumbernya bukan NULL.
Bidang bilangan bulat atau bilangan pecahansum, ` avg`, ` min`, maxMenghitung nilai yang dipertahankan yang tidak null.
Bidang string atau TIMESTAMPTZ min, maxMemilih nilai yang disimpan non-null minimum atau maksimum.
"*"countMenghitung setiap kandidat yang dipertahankan dalam bucket. Hasilnya sesuai dengan bucket.count.
_scoresum, avg, min, maxMenghitung nilai kesamaan atau jarak ANN untuk kandidat yang dipertahankan.

SearchAggregation.order menerima kunci-kunci berikut:

Kunci urutanArti
Alias metrikMengurutkan berdasarkan nilai yang dihitung dalam metrics pada tingkat agregasi yang sama, seperti avg_price.
_countMengurutkan berdasarkan jumlah kandidat yang disimpan di setiap bucket.
_keyMengurutkan 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.

Buat kunci bucket gabungan

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

Lihat bucket dengan hasil yang representatif

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": []
}

ParameterTujuan
top_hitsOpsional. Mengonfigurasi entitas representatif untuk tingkat agregasi ini. Jika diabaikan, ` bucket.hits ` akan kosong dan anggaran kandidat per kunci secara default ditetapkan menjadi satu.
TopHits.sizeMengembalikan hingga dua entitas representatif dari setiap bucket yang dipilih dan menetapkan anggaran kandidat per-kunci menjadi dua untuk seluruh pohon agregasi.
TopHits.sortMengurutkan 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"}],
        ),
    ),
)

Lihat hasil bucket bersarang

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_groups bucket akar berisi bucket merek anak. Bucket Merek B yang ditampilkan berisi satu kandidat yang dipertahankan serta nilai avg_rating dan brand_count miliknya sendiri.
  • Daftar hits pada bucket akar kosong karena agregasi akar tidak mengonfigurasi top_hits. Bucket anak Merek B berisi hit representatif karena top_hits dikonfigurasi di sub_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.

Pilihlah berdasarkan bentuk hasil utama aplikasi:

Kebutuhan utamaPilihanRespons yang akan digunakan
Mengembalikan daftar entitas yang diurutkan secara standar dengan lebih sedikit nilai berulang dalam bidang pengelompokanPencarian PengelompokanHasil pencarian datar untuk setiap vektor kueri
Periksa atau bandingkan grup sebagai bucket, dengan kunci, jumlah, metrik, urutan, hasil yang representatif, atau bucket anakAgregasi PencarianAggregationBucket 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.