Episode ini membedah API query ChromaDB: query_texts dan query_embeddings, pengaturan n_results, serta parameter include untuk memilih dokumen, metadatas, distances, atau embeddings yang dikembalikan, lengkap dengan interpretasi distance vs similarity.

Di episode 4 kalian sudah bisa menyimpan dan mengelola data. Sekarang masuk ke bagian yang membuat ChromaDB istimewa: querying dan semantic search. Di sinilah kalian bertanya dalam bahasa alami dan ChromaDB menemukan dokumen yang bermakna sama, bukan sekadar yang hurufnya sama.
Episode 5 membedah API query secara menyeluruh: dua cara memberikan input (query_texts dan query_embeddings), berapa banyak hasil (n_results), apa saja yang dikembalikan (include), serta cara membaca hasil — terutama perbedaan distance dan similarity yang sering membingungkan.
Cara paling alami: berikan teks dan biarkan ChromaDB men-embed-nya sendiri:
hasil = collection.query(
query_texts=["Bagaimana cara deploy aplikasi?"],
n_results=3,
)collection.query(query_texts=["..."], n_results=3) men-embed teks query dengan embedding function collection, mencari 3 vektor terdekat, lalu mengembalikan hasil. Ini adalah pintu utama semantic search.
Jika embedding query sudah dibangkitkan di luar — misalnya dari model yang sama dengan data — gunakan query_embeddings:
hasil = collection.query(
query_embeddings=[[0.2, 0.8, 0.4, 0.6]],
n_results=2,
)Perbedaan keduanya hanya di proses embed. collection.query(query_embeddings=[[...]]) memakai vektor yang diberikan langsung. Untuk pipeline RAG yang men-embed query dengan model khusus, bentuk ini lebih efisien karena menghemat satu panggilan.
Secara default, query mengembalikan ids, documents, metadatas, dan distances. Kalian bisa mengatur apa saja yang dikembalikan lewat include:
hasil = collection.query(
query_texts=["Apa itu Kubernetes?"],
n_results=2,
include=["documents", "metadatas", "distances"],
)Opsi yang tersedia untuk include=["documents", "metadatas", "distances"]:
documents: teks sumber, wajib untuk RAG.metadatas: atribut seperti sumber dan tanggal.distances: nilai jarak hasil terhadap query.embeddings: vektor hasil, berguna untuk analisis lanjutan.Semakin banyak yang diminta, semakin besar payload yang dikembalikan. Di production, minta hanya yang dibutuhkan untuk menghemat bandwidth.
Konsep yang paling sering salah dipahami: ChromaDB mengembalikan distance, bukan similarity. Semakin kecil distance, semakin mirip hasilnya:
hasil = collection.query(query_texts=["deploy aplikasi"], n_results=2)
for i, dok in enumerate(hasil["documents"][0]):
jarak = hasil["distances"][0][i]
print(f"{dok} -> jarak {jarak:.4f}")Pada kode di atas, hasil["documents"][0] adalah list hasil untuk query pertama, dan hasil["distances"][0] adalah jarak masing-masing. Hasil diurutkan dari jarak terkecil (paling relevan) ke terbesar.
Distance bergantung pada metrik yang dipakai (episode 9). Untuk cosine distance, similarity dihitung sebagai:
similarity = 1.0 - jarakRumus similarity = 1.0 - jarak berlaku untuk cosine. Jadi jarak 0.15 berarti similarity 0.85. Ingat kebalikannya saat membandingkan hasil antar collection dengan metrik berbeda.
Warning
Jangan membandingkan nilai distance antara collection yang memakai metrik berbeda. Cosine, L2, dan inner product menghasilkan skala jarak yang berbeda sama sekali — episode 9 akan menjelaskan kapan memakai yang mana.
query_texts menerima list, sehingga satu panggilan bisa menjawab banyak pertanyaan:
hasil = collection.query(
query_texts=["Apa itu Docker?", "Apa itu Kubernetes?", "Apa itu CI/CD?"],
n_results=1,
)
for i, dok in enumerate(hasil["documents"]):
print(f"Q{i}: {dok[0]}")Struktur hasil selalu dua level: hasil["documents"][i] adalah list hasil untuk query ke-i. Batch query collection.query(query_texts=[...]) memangkas latensi karena satu round-trip menangani banyak pertanyaan — pola yang akan kita pakai lagi untuk multi-query di episode 19.
Jika query mengembalikan dokumen yang tidak relevan, beberapa kemungkinan: embedding function collection berbeda dari yang dipakai membangkitkan data, atau ukuran chunk dokumen (episode 10) terlalu besar sehingga makna tercampur. Periksa dulu embedding function, lalu cek strategi chunking.
Semua argumen list di add, query, dan lainnya harus punya panjang yang sama. Error ini biasanya dari query_texts yang tidak berupa list:
hasil = collection.query(query_texts="deploy")
hasil = collection.query(query_texts=["deploy"])Selalu bungkus query tunggal dalam list. collection.query(query_texts=["deploy"]) adalah bentuk yang benar — kesalahan ini yang paling sering terjadi di forum komunitas.
Episode 5 membuka kekuatan inti ChromaDB: querying dan semantic search. Kalian sekarang bisa memberi query dalam bentuk teks atau vektor, mengontrol jumlah dan isi hasil lewat n_results dan include, membaca hasil yang terurut dari jarak terkecil, dan menghindari jebakan distance versus similarity.
Inti yang harus dibawa pulang:
query_texts untuk query teks; query_embeddings untuk query vektor.n_results menentukan jumlah hasil; include menentukan isi hasil.1 - distance.Di episode 6 selanjutnya kita akan membahas embeddings dan embedding functions — model bawaan ONNX MiniLM yang berjalan lokal, cara mengganti ke sentence-transformers atau OpenAI, integrasi pre-computed embeddings, dan cara menulis fungsi embedding custom. Ini menentukan kualitas semantic search kalian secara keseluruhan.