Topik ini membahas pembaruan dokumen dengan metode updateOne dan updateMany beserta operator update seperti $set, $inc, $push, dan $pull. Pembahasan mencakup bentuk hasil kembalian kedua metode, perilaku setiap operator pada field yang sudah ada maupun yang belum ada, serta perbedaan cakupan keduanya. Seluruh contoh dijalankan pada koleksi buku di basis data perpustakaan dengan data contoh yang diisi di awal, sehingga setiap perubahan dapat diverifikasi melalui pembacaan ulang dokumennya.
Memperbarui satu dokumen dengan updateOne#
Metode updateOne menerima dua argumen, yaitu filter yang memilih dokumen dan dokumen pembaruan yang menyatakan perubahannya. Dokumen pembaruan wajib memuat operator update (update operator), yaitu operator yang diawali tanda dolar dan menyatakan cara mengubah field. Operator $set mengganti nilai field yang sudah ada, atau membuat field baru apabila field itu belum ada pada dokumen.
Siapkan data contoh berupa enam buku.
use perpustakaanswitched to db perpustakaandb.buku.insertMany([
{ judul: "Algoritma Pemrograman", pengarang: "Budi Santoso", tahun: 2020, stok: 4, tags: ["pemrograman"] },
{ judul: "Jaringan Komputer Dasar", pengarang: "Ali Rahman", tahun: 2019, stok: 2, tags: ["jaringan"] },
{ judul: "Basis Data Dokumen", pengarang: "Citra Melati", tahun: 2022, stok: 7, tags: ["basis data"] },
{ judul: "Pemrograman Python", pengarang: "Budi Santoso", tahun: 2023, stok: 3, tags: ["pemrograman", "python"] },
{ judul: "Statistika untuk Data", pengarang: "Rina Wulandari", tahun: 2021, stok: 5, tags: ["statistika", "data"] },
{ judul: "Keamanan Jaringan", pengarang: "Ali Rahman", tahun: 2021, stok: 1, tags: ["jaringan", "keamanan"] }
]){
acknowledged: true,
insertedIds: {
'0': ObjectId('6ae8937a773ea6be8c8de666'),
'1': ObjectId('6ae8937a773ea6be8c8de667'),
'2': ObjectId('6ae8937a773ea6be8c8de668'),
'3': ObjectId('6ae8937a773ea6be8c8de669'),
'4': ObjectId('6ae8937a773ea6be8c8de66a'),
'5': ObjectId('6ae8937a773ea6be8c8de66b')
}
}Perbarui stok salah satu buku dengan $set, lalu baca ulang dokumennya untuk memastikan perubahannya.
db.buku.updateOne({ judul: "Algoritma Pemrograman" }, { $set: { stok: 6 } }){
acknowledged: true,
insertedId: null,
matchedCount: 1,
modifiedCount: 1,
upsertedCount: 0
}db.buku.findOne({ judul: "Algoritma Pemrograman" }){
_id: ObjectId('6ae874419d05928a9f8de666'),
judul: 'Algoritma Pemrograman',
pengarang: 'Budi Santoso',
tahun: 2020,
stok: 6,
tags: [ 'pemrograman' ]
}Hasil kembalian updateOne memuat acknowledged, insertedId yang selalu null pada operasi pembaruan, serta matchedCount, modifiedCount, dan upsertedCount. Nilai matchedCount: 1 berarti satu dokumen cocok dengan filter, sedangkan modifiedCount: 1 berarti satu dokumen benar-benar berubah. Nilai upsertedCount selalu 0 pada contoh di sini karena pilihan penyisipan otomatis (upsert) tidak diaktifkan. Pembacaan ulang pada blok terakhir menunjukkan field stok yang kini bernilai 6.
Operator $set juga dipakai untuk menambah field baru pada dokumen yang sudah ada. Field edisi pada data contoh tidak ada sejak awal, sehingga perintah berikut menambahkannya pada buku yang sudah tersimpan.
db.buku.updateOne({ judul: "Jaringan Komputer Dasar" }, { $set: { edisi: 2 } }){
acknowledged: true,
insertedId: null,
matchedCount: 1,
modifiedCount: 1,
upsertedCount: 0
}Field edisi belum ada pada data awal, tetapi $set membuatnya begitu perintah dijalankan. Kelenturan ini mengikuti sifat dokumen MongoDB yang tidak menuntut struktur seragam antardokumen, sehingga penambahan field dapat dilakukan per dokumen tanpa mengubah struktur koleksi. Field yang baru muncul pada sebagian dokumen dapat dikenali kembali dengan $exists apabila perbedaannya perlu diperlakukan khusus.
Menambah dan mengurangi nilai angka dengan $inc#
Operator $inc menambah atau mengurangi nilai field berupa angka tanpa perlu membaca nilai lamanya terlebih dahulu. Nilai negatif pada operator ini berfungsi sebagai pengurang, sehingga satu operator mencakup dua arah perubahan. Pola ini cocok untuk stok perpustakaan yang bertambah setiap penerimaan buku baru dan berkurang setiap peminjaman.
db.buku.updateOne({ judul: "Pemrograman Python" }, { $inc: { stok: -1 } }){
acknowledged: true,
insertedId: null,
matchedCount: 1,
modifiedCount: 1,
upsertedCount: 0
}db.buku.findOne({ judul: "Pemrograman Python" }, { judul: 1, stok: 1 }){
_id: ObjectId('6ae874419d05928a9f8de669'),
judul: 'Pemrograman Python',
stok: 2
}Hasil pembacaan ulang menunjukkan stok yang berkurang dari 3 menjadi 2, tanpa perintah pembacaan maupun penulisan ulang nilai lamanya. Apabila field yang dituju belum ada, $inc membuat field tersebut dengan nilai sebesar angka yang diberikan. Operator ini hanya berlaku pada nilai numerik, sehingga $inc pada field bertipe string ditolak dengan pesan error.
Penambahan yang dikerjakan $inc berlangsung di sisi server dalam satu operasi atomik pada satu dokumen. Dua proses yang mengubah stok dokumen yang sama secara bersamaan tidak saling menimpa hasil, karena setiap pengurangan diterapkan terhadap nilai terbaru. Pola baca-ubah-tulis manual, yaitu membaca nilai ke aplikasi lalu menulisnya kembali, justru rentan kehilangan perubahan pada situasi semacam ini.
Memperbarui banyak dokumen dengan updateMany#
Metode updateMany menerapkan satu dokumen pembaruan kepada seluruh dokumen yang cocok dengan filter. Filternya ditulis dengan aturan yang sama seperti filter find, sehingga operator query seperti $in dan $gte dapat dipakai langsung. Hasil kembaliannya berisi jumlah dokumen yang cocok dan jumlah dokumen yang berubah.
db.buku.updateMany({ pengarang: "Ali Rahman" }, { $set: { rak: "C1" } }){
acknowledged: true,
insertedId: null,
matchedCount: 2,
modifiedCount: 2,
upsertedCount: 0
}Hasilnya matchedCount: 2 dan modifiedCount: 2, karena dua buku karya Ali Rahman sama-sama mendapat field rak. Nilai yang ditetapkan sama untuk keduanya karena keduanya memenuhi filter yang sama. Menjalankan perintah yang identik untuk kedua kalinya memberi hasil yang berbeda.
db.buku.updateMany({ pengarang: "Ali Rahman" }, { $set: { rak: "C1" } }){
acknowledged: true,
insertedId: null,
matchedCount: 2,
modifiedCount: 0,
upsertedCount: 0
}Eksekusi kedua tetap menemukan dua dokumen yang cocok, tetapi modifiedCount bernilai 0 karena nilainya sudah sama dengan yang akan ditetapkan. Pembedaan matchedCount dan modifiedCount seperti ini berguna untuk memeriksa apakah sebuah pembaruan massal benar-benar mengubah data atau hanya menyentuh dokumen tanpa perubahan apa pun. Nilai kembalian semacam ini juga memudahkan pengujian, karena eksekusi ulang yang aman dapat dikenali dari modifiedCount yang tetap 0.
Mengubah array dengan $push dan $pull#
Operator $push menambahkan satu elemen ke akhir array, sedangkan $pull membuang seluruh elemen yang cocok dengan nilai yang diberikan. Keduanya bekerja pada field bertipe array dan dipakai bersama updateOne maupun updateMany. Pada data buku, array tags menyimpan label yang dapat bertambah maupun berkurang seiring waktu.
db.buku.updateOne({ judul: "Basis Data Dokumen" }, { $push: { tags: "populer" } }){
acknowledged: true,
insertedId: null,
matchedCount: 1,
modifiedCount: 1,
upsertedCount: 0
}db.buku.findOne({ judul: "Basis Data Dokumen" }, { judul: 1, tags: 1 }){
_id: ObjectId('6ae874419d05928a9f8de668'),
judul: 'Basis Data Dokumen',
tags: [ 'basis data', 'populer' ]
}Pembacaan ulang menunjukkan label populer yang bergabung di akhir array tanpa mengganggu label yang sudah ada. Sebaliknya, $pull membuang elemen yang cocok dari array pada buku lain. Keduanya saling melengkapi untuk menjaga isi array mengikuti kondisi terbaru.
db.buku.updateOne({ judul: "Pemrograman Python" }, { $pull: { tags: "python" } }){
acknowledged: true,
insertedId: null,
matchedCount: 1,
modifiedCount: 1,
upsertedCount: 0
}db.buku.findOne({ judul: "Pemrograman Python" }, { judul: 1, tags: 1 }){
_id: ObjectId('6ae874419d05928a9f8de669'),
judul: 'Pemrograman Python',
tags: [ 'pemrograman' ]
}Hasilnya array tags yang tinggal memuat satu label karena elemen python telah dibuang. Apabila elemen yang sama muncul lebih dari satu kali, $pull membuang semuanya sekaligus. Perilaku ini berbeda dari $push yang tidak melakukan pemeriksaan apa pun terhadap isi array.
Kesalahan umum#
Kesalahan yang paling sering terjadi adalah menuliskan perubahan field secara langsung tanpa operator update. Bentuk seperti ini terlihat masuk akal karena mirip dengan dokumen yang disisipkan, tetapi mongosh menolaknya dengan error. Dokumen pembaruan yang sah selalu menyatakan operasinya lewat operator yang diawali tanda dolar.
db.buku.updateOne({ judul: "Algoritma Pemrograman" }, { stok: 6 })Uncaught
MongoInvalidArgumentError: Update document requires atomic operatorsPesan Update document requires atomic operators muncul karena dokumen pembaruan tanpa operator tidak mempunyai makna yang terdefinisi, sehingga perintah ditolak sebelum dikirim ke server. Perbaikannya adalah membungkus perubahan dalam operator yang sesuai, misalnya { $set: { stok: 6 } } untuk mengganti nilai atau { $inc: { stok: 1 } } untuk menaikkannya satu tingkat. Nama operatornya harus dipilih sesuai maksud, karena setiap operator mempunyai perilaku yang berbeda terhadap nilai lama.
Kesalahan berikutnya adalah mengasumsikan updateOne mengubah seluruh dokumen yang cocok. Apabila filternya luas, misalnya hanya menyaring nama pengarang, satu-satunya dokumen yang berubah adalah dokumen pertama menurut urutan penyimpanan, sedangkan sisanya tidak tersentuh. Pastikan cakupan metode dipilih dengan sengaja, yaitu updateOne untuk satu dokumen yang dituju secara spesifik dan updateMany untuk perubahan massal yang memang diinginkan.
Ringkasan#
updateOnemengubah satu dokumen pertama yang cocok, sedangkanupdateManymengubah seluruh dokumen yang cocok, dan keduanya mengembalikanmatchedCountbesertamodifiedCount.$setmengganti nilai field atau membuat field baru, sedangkan$incmenambah dan mengurangi nilai angka tanpa membaca nilai lamanya.$pushmenambah elemen ke akhir array tanpa pemeriksaan duplikasi, sedangkan$pullmembuang seluruh elemen yang cocok.- Dokumen pembaruan wajib memuat operator yang diawali tanda dolar, dan tanpa operator perintah ditolak sebelum sampai ke server.
Referensi#
- Update Documents — MongoDB Manual — Tutorial resmi pembaruan dokumen beserta contoh operatornya.
- db.collection.updateOne() — MongoDB Manual — Dokumentasi metode updateOne dan hasil kembaliannya.
- db.collection.updateMany() — MongoDB Manual — Dokumentasi metode updateMany untuk pembaruan banyak dokumen.
- Update Operators — MongoDB Manual — Daftar operator update beserta kelompok field dan array.
- $push — MongoDB Manual — Dokumentasi operator $push untuk penambahan elemen array.
- $pull — MongoDB Manual — Dokumentasi operator $pull untuk pembuangan elemen array.