Penerbit menarik sebuah judul dari peredaran, dan katalog toko buku harus mengikutinya. Inilah tugas deleteOne(filter): menemukan document yang cocok dengan filter lalu menghapusnya dari collection. Operasi ini tidak punya tombol undo — sekali dihapus, document hanya kembali bila kita menyisipkannya lagi — sehingga kebiasaan menulis filter yang tepat menjadi bagian tak terpisahkan dari bab ini.
Menghapus Satu Document #
Bentuknya sederhana: satu argument filter, persis seperti yang kita pakai di find() dan updateOne(). Kita mulai dari data contoh yang sudah dikenal:
use latihan_crud2
db.buku.drop()
db.buku.insertMany([
{ judul: "Laskar Pelangi", penulis: "Andrea Hirata", harga: 95000, stok: 12, kategori: "Fiksi", tag: ["novel", "bestseller"], rating: 4.6 },
{ judul: "Bumi Manusia", penulis: "Pramoedya Ananta Toer", harga: 110000, stok: 8, kategori: "Fiksi", tag: ["novel", "klasik"], rating: 4.8 },
{ judul: "Atomic Habits", penulis: "James Clear", harga: 135000, stok: 20, kategori: "Pengembangan Diri", tag: ["nonfiksi", "bestseller"], rating: 4.7 },
{ judul: "Filosofi Teras", penulis: "Henry Manampiring", harga: 89000, stok: 0, kategori: "Pengembangan Diri", tag: ["nonfiksi"], rating: 4.5 },
{ judul: "Clean Code", penulis: "Robert C. Martin", harga: 165000, stok: 5, kategori: "Teknologi", tag: ["pemrograman", "bestseller"], rating: 4.4 }
])Output yang Dihasilkan:
switched to db latihan_crud2
true
{
acknowledged: true,
insertedIds: {
'0': ObjectId('6ad38836674b2c3792c4a703'),
'1': ObjectId('6ad38836674b2c3792c4a704'),
'2': ObjectId('6ad38836674b2c3792c4a705'),
'3': ObjectId('6ad38836674b2c3792c4a706'),
'4': ObjectId('6ad38836674b2c3792c4a707')
}
}Hapus Bumi Manusia dari katalog, lalu hitung sisa isinya:
db.buku.deleteOne({ judul: "Bumi Manusia" })
db.buku.countDocuments({})Output yang Dihasilkan:
{ acknowledged: true, deletedCount: 1 }
4Hasilnya adalah DeleteResult — tipe hasil paling ringkas di antara method tulis: acknowledged: true berarti server mengonfirmasi penghapusan, dan deletedCount: 1 menghitung document yang benar-benar dihapus. Angka 4 dari countDocuments() memastikan lima data contoh tinggal empat.
Bila filter tidak menemukan sasaran, deleteOne() tidak melempar galat — ia hanya melapor nol:
db.buku.deleteOne({ judul: "Buku yang Tidak Ada" })Output yang Dihasilkan:
{ acknowledged: true, deletedCount: 0 }deletedCount: 0 dengan acknowledged: true berarti perintah sukses dieksekusi tetapi tidak ada document yang cocok — pola yang sama dengan matchedCount: 0 pada operasi update.
Filter paling aman untuk penghapusan adalah _id: nilainya dijamin unik per collection, sehingga hasilnya tidak pernah bergantung urutan penemuan. Pola umumnya dua langkah — ambil document lebih dulu, lalu hapus berdasarkan _id-nya:
const sasaran = db.buku.findOne({ judul: "Clean Code" }, { _id: 1 })
db.buku.deleteOne({ _id: sasaran._id })
db.buku.countDocuments({})Output yang Dihasilkan:
{ acknowledged: true, deletedCount: 1 }
3findOne() dengan projection { _id: 1 } hanya memuat identifier yang kita butuhkan; deleteOne({ _id: ... }) lalu menghapus tepat document itu. Pola “cari dulu, hapus dengan _id” seperti ini adalah bentuk paling defensif dari deleteOne().
Bahaya Filter Kosong dan Filter Longgar #
Dua jebakan menanti filter yang ceroboh. Yang pertama: filter kosong. deleteOne({}) cocok dengan semua document, sehingga shell menghapus document pertama yang ditemukannya — pada praktiknya document yang paling awal masuk:
db.buku.deleteOne({})
db.buku.find({}, { judul: 1 })Output yang Dihasilkan:
{ acknowledged: true, deletedCount: 1 }
[
{ _id: ObjectId('6ad38836674b2c3792c4a705'), judul: 'Atomic Habits' },
{ _id: ObjectId('6ad38836674b2c3792c4a706'), judul: 'Filosofi Teras' }
]Laskar Pelangi — document pertama hasil insertMany() — terhapus, meskipun tidak ada niat menyebut namanya. Urutan “document pertama” mengikuti natural order, urutan penyimpanan internal di disk; pada collection kecil tanpa sort(), urutan itu umumnya sama dengan urutan penyisipan, tetapi MongoDB tidak pernah menjaminnya — mengandalkan urutan ini untuk memilih sasaran penghapusan adalah kebiasaan yang keliru.
Jebakan kedua: filter longgar. Filter { kategori: "Pengembangan Diri" } mencocokkan dua buku; deleteOne() tetap menghapus hanya satu di antaranya dan diam tentang sisanya, sehingga hasil akhirnya bergantung pada document mana yang kebetulan ditemukan lebih dulu. Ketika niatnya memang menghapus satu dari banyak kandidat, pastikan kandidat itu teridentifikasi unik — pola filter _id di bagian sebelumnya adalah jawabannya.
Sebelum lanjut, bersihkan database latihan:
db.dropDatabase()Output yang Dihasilkan:
{ ok: 1, dropped: 'latihan_crud2' }Rangkuman #
deleteOne(filter)menghapus document pertama yang cocok dengan filter; hasilnyaDeleteResultberisiacknowledgeddandeletedCount.deletedCount: 0bukan galat — filter hanya tidak menemukan sasaran.- Filter kosong
{}menghapus document pertama yang ditemukan; filter longgar membuat hasil bergantung urutan penemuan. - Uji filter dengan
find()ataucountDocuments()sebelum memakainya untuk menghapus. - Tidak ada undo — document yang terhapus hanya kembali lewat insert baru.
Satu document sudah jelas mekanismenya; Chapter berikutnya mengangkat versi massalnya: deleteMany() — lengkap dengan risiko terbesarnya.