Episode ini membahas seluruh operasi manipulasi data di ChromaDB: add, get, update, upsert, delete, count, dan modify, beserta kombinasi ids, documents, metadatas, dan embeddings yang bisa disimpan sekaligus dalam satu panggilan.

Collection pertama sudah berdiri di episode 3. Sekarang saatnya menguasai seluruh operasi manipulasi data — CRUD dasar. Meski terdengar sederhana, memahami setiap operasi dan perbedaannya adalah kunci menghindari bug yang mengganggu di produksi: data terduplikasi, dokumen yang tidak bisa diperbarui, atau penghapusan yang menghapus terlalu banyak.
Episode 4 membahas tujuh operasi: add, get, update, upsert, delete, count, dan modify. Empat operasi terakhir sama seperti database lain, tapi tiga yang pertama — terutama update versus upsert — sering membuat kalian tersandung. Mari kita mulai.
add menyimpan data baru ke collection. Setiap id harus unik; menambah id yang sudah ada akan memicu error UniqueConstraintError:
collection.add(
ids=["dok-1", "dok-2"],
documents=["Teks pertama", "Teks kedua"],
metadatas=[{"sumber": "web"}, {"sumber": "pdf"}],
)Perhatikan pola argumen berbasis list: ids, documents, dan metadatas semuanya berupa list dengan panjang sama. collection.add(...) adalah satu-satunya jalan untuk menambah data baru; semua id yang dikirim harus belum ada.
Jika embedding sudah dibangkitkan di luar ChromaDB, kalian bisa memberikannya langsung:
collection.add(
ids=["dok-3"],
embeddings=[[0.12, 0.45, 0.87, 0.22]],
metadatas=[{"sumber": "api"}],
)Saat menyediakan embeddings, pastikan dimensinya konsisten dengan embedding function collection. collection.add(ids=["dok-3"], embeddings=[[...]]) memberi kalian kendali penuh — pola ini akan dipakai lagi di episode 6.
get adalah cara membaca data. Tanpa argumen, ia mengembalikan semua isi collection:
semua = collection.get()Untuk menyaring, berikan ids atau where (filter metadata — episode 7 akan membedahnya):
dua_item = collection.get(ids=["dok-1", "dok-2"])
print(dua_item["metadatas"])collection.get(ids=["dok-1", "dok-2"]) mengembalikan dict dengan keys ids, documents, metadatas, dan embeddings (jika diminta lewat include). Ini kontras penting dengan query di episode 5: get berdasarkan id atau metadata, sedangkan query berdasarkan kemiripan vektor.
update mengubah dokumen, metadata, atau embedding pada id yang sudah ada. Id yang belum ada akan diabaikan tanpa error — ini perilaku yang perlu kalian sadari:
collection.update(
ids=["dok-2"],
metadatas=[{"sumber": "pdf", "status": "revisi"}],
)Kode di atas mengganti metadata dok-2 dengan dict baru. collection.update(ids=["dok-2"], metadatas=[...]) tidak menambah data baru — itu tugas upsert.
Penting: update tidak membangkitkan embedding otomatis dari dokumen baru jika embedding function aktif. Untuk mengganti embedding, berikan embeddings eksplisit:
collection.update(ids=["dok-1"], embeddings=[[0.5, 0.2, 0.9, 0.1]])Aturan ini membingungkan banyak orang. Ingat saja: add boleh mengandalkan embedding otomatis; update mengharapkan embedding eksplisit bila perlu.
upsert menggabungkan keduanya: id yang belum ada akan ditambahkan, id yang sudah ada akan diperbarui. Ini operasi yang paling nyaman untuk sinkronisasi data:
collection.upsert(
ids=["dok-2", "dok-4"],
documents=["Teks kedua versi baru", "Teks keempat"],
metadatas=[{"sumber": "pdf"}, {"sumber": "manual"}],
)Pada contoh di atas, dok-2 diperbarui (karena sudah ada) dan dok-4 ditambahkan (karena baru). collection.upsert(...) adalah pilihan terbaik untuk job sinkronisasi berkala dari API atau web scraping.
Success
Jika kalian tidak yakin data sudah ada atau belum, pakai upsert. Untuk data baru yang dijamin unik, pakai add agar kesalahan duplikasi langsung terdeteksi.
delete menghapus berdasarkan id atau filter metadata. Menghapus berdasarkan ids adalah pola paling umum:
collection.delete(ids=["dok-4"])collection.delete(ids=["dok-4"]) menghapus item yang cocok dan tidak mengembalikan error jika id tidak ditemukan. Untuk penghapusan massal, pakai filter where (episode 7) — misalnya menghapus semua berita dengan kategori "draft".
count mengembalikan jumlah item:
jumlah = collection.count()
print(jumlah)Terakhir, modify bukan untuk data, melainkan untuk konfigurasi collection itu sendiri — mengganti nama atau metadata:
collection.modify(name="artikel-tech-v2")collection.modify(name="artikel-tech-v2") mengganti nama collection di tempatnya, tanpa menghapus data. Berguna saat konvensi penamaan berubah di tengah development.
ringkasan = {
"add": "id baru, error jika sudah ada, embedding otomatis",
"get": "baca berdasarkan id atau where",
"update": "ubah yang sudah ada saja, id baru diabaikan",
"upsert": "tambah atau ubah sekaligus",
"delete": "hapus berdasarkan id atau where",
"count": "jumlah item",
"modify": "ubah konfigurasi collection",
}
for nama, keterangan in ringkasan.items():
print(f"{nama}: {keterangan}")Simpan mental tabel di atas — ringkasan["upsert"] akan menjadi teman setia kalian untuk sinkronisasi data harian.
Episode 4 melengkapi kalian dengan seluruh operasi CRUD ChromaDB: add untuk data baru, get untuk membaca, update dan upsert untuk mengubah (dengan perbedaan krusial soal id yang belum ada), delete untuk menghapus, count untuk menghitung, serta modify untuk mengubah konfigurasi collection.
Inti yang harus dibawa pulang:
add menolak id duplikat; upsert menerimanya dan memperbarui.update tidak membangkitkan embedding otomatis; berikan embeddings eksplisit.get membaca berdasarkan id atau metadata; query membaca berdasarkan kemiripan.delete dan get menerima filter where untuk operasi massal.modify mengubah konfigurasi collection, bukan isinya.Di episode 5 selanjutnya kita akan membahas querying dan semantic search — API query dengan query_texts dan query_embeddings, pengaturan n_results, parameter include, serta cara menafsirkan distance versus similarity. Di sinilah ChromaDB mulai terasa ajaib.