Episode ini membahas metadata filtering dengan klausa where: operator $eq, $ne, $in, $nin, $gt, $lt, $gte, dan $lte, metadata bersarang, logika $and dan $or, serta pencarian dokumen lewat $contains, $not_contains, dan regex.

Semantic search saja tidak selalu cukup. Bayangkan kalian punya jutaan berita dan ingin menjawab "berapa kenaikan inflasi bulan lalu?" — tanpa tahu kapan "bulan lalu". Di sinilah metadata filtering berperan: menyaring data berdasarkan atribut terstruktur sebelum atau saat pencarian vektor berjalan.
Episode 7 membahas klausa where secara menyeluruh: operator perbandingan, metadata bersarang, kombinasi $and dan $or, serta where_document untuk pencarian di dalam teks dokumen memakai $contains dan regex. Filter ini yang mengubah ChromaDB dari sekadar "cari mirip" menjadi "cari mirip dengan syarat".
Klausa where berbentuk dict: key adalah nama field metadata, value adalah dict operator. ChromaDB menyediakan delapan operator dasar:
$eq: sama dengan$ne: tidak sama dengan$in: termasuk dalam list$nin: tidak termasuk dalam list$gt: lebih besar dari$lt: lebih kecil dari$gte: lebih besar atau sama dengan$lte: lebih kecil atau sama denganhasil = collection.query(
query_texts=["inflasi"],
n_results=10,
where={"kategori": "ekonomi"},
)Contoh di atas menerapkan shorthand: where={"kategori": "ekonomi"} sama dengan $eq. Hanya item dengan metadata kategori: ekonomi yang dipertimbangkan dalam pencarian vektor.
Beberapa kondisi pada field yang sama ditulis berurutan dalam satu dict:
hasil = collection.get(
where={"tanggal": {"$gte": "2026-06-01", "$lt": "2026-07-01"}},
)where={"tanggal": {"$gte": "2026-06-01", "$lt": "2026-07-01"}} mengambil semua item dengan tanggal dalam rentang Juni 2026. Ini pola penting untuk filter temporal — misalnya retention policy yang akan kita bahas di episode 16.
$in dan $nin sangat berguna untuk filter kategori atau status:
hasil = collection.get(
where={"status": {"$in": ["published", "draft"]}},
)
hasil = collection.get(
where={"status": {"$nin": ["archived", "deleted"]}},
)where={"status": {"$in": ["published", "draft"]}} mengambil item dengan status di dalam list; $nin mengambil yang sebaliknya. Kombinasi ini menggantikan banyak klausa $or yang bertele-tele.
Metadata ChromaDB bisa bersarang — key seperti "penulis.nama" otomatis diinterpretasikan sebagai akses ke nested dict:
hasil = collection.get(
where={"penulis.nama": {"$eq": "Arman"}},
)Jika metadata item adalah {"penulis": {"nama": "Arman", "role": "admin"}}, maka where={"penulis.nama": {"$eq": "Arman"}} mencocokkannya. Akses nested memakai titik sebagai pemisah level. Metadata bersarang mempermudah model data yang rapi — misalnya menaruh konteks lengkap seperti penulis, versi, dan source di bawah satu key, yang akan dibahas penuh di episode 10.
Untuk kondisi lintas field, pakai $and atau $or. Keduanya menerima list of where-clauses:
hasil = collection.get(
where={
"$and": [
{"kategori": "ekonomi"},
{"tanggal": {"$gte": "2026-06-01"}},
]
},
)hasil = collection.get(
where={
"$or": [
{"kategori": "ekonomi"},
{"kategori": "keuangan"},
]
},
)where={"$and": [...]} mengharuskan semua kondisi terpenuhi; where={"$or": [...]} cukup satu. Keduanya bisa ditumpuk — misalnya where={"$and": [{"$or": [...]}, {"status": "published"}], ...} — sehingga ChromaDB mengevaluasi pohon kondisi yang kompleks secara penuh.
Selain metadata, ChromaDB bisa menyaring berdasarkan isi dokumen lewat where_document. Operator utamanya $contains (mengandung teks) dan $not_contains:
hasil = collection.query(
query_texts=["database"],
n_results=5,
where_document={"$contains": "ChromaDB"},
)where_document={"$contains": "ChromaDB"} hanya mengembalikan dokumen yang memuat kata "ChromaDB". Ini adalah full-text filter yang bekerja di dalam satu query vektor — jembatan menuju episode 8.
Untuk pola yang lebih fleksibel, ChromaDB mendukung regex di where_document:
hasil = collection.get(
where_document={"$contains": "v[0-9]+\.[0-9]+"},
)where_document={"$contains": "v[0-9]+\.[0-9]+"} mencocokkan dokumen yang memuat pola seperti v1.5 atau v2.3 — berguna untuk mencari versi software. Ingat aturan escape: regex ditulis dalam string Python, jadi backslash perlu didouble jika perlu.
Di produksi, filter digunakan sekaligus — metadata dan dokumen:
hasil = collection.query(
query_texts=["rekomendasi database vektor"],
n_results=3,
where={
"$and": [
{"status": "published"},
{"topik": "database"},
]
},
where_document={"$contains": "Chroma"},
)Pola di atas — semantic search dibatasi status, topik, dan isi dokumen — adalah template RAG yang realistis. collection.query(...) mengevaluasi semua filter sebelum menyusun hasil berdasarkan vektor.
Episode 7 melengkapi kalian dengan presisi: klausa where untuk menyaring metadata dengan delapan operator, akses metadata bersarang, logika $and dan $or, serta where_document untuk pencarian teks dan regex di dalam dokumen. Filter adalah pembeda antara hasil yang "mirip" dan hasil yang "tepat".
Inti yang harus dibawa pulang:
where menyaring metadata; where_document menyaring isi dokumen.$eq, $ne, $in, $nin, $gt, $lt, $gte, $lte.penulis.nama.$and dan $or bisa ditumpuk untuk logika kompleks.$contains dan $not_contains untuk full-text di dokumen.where_document membuka pencarian pola seperti versi software.Di episode 8 selanjutnya kita akan membahas full-text dan hybrid search — pencarian keyword yang lebih lengkap dengan skor relevansi, strategi menggabungkan vector, full-text, dan metadata, serta pendekatan fusion dan rerank untuk hasil RAG yang akurat. Ini membawa ChromaDB selangkah lebih dekat ke produksi.