8-bo‘lim
O'chirish va almashtirish
deleteOne va deleteMany, bo'sh filtr xavfi, replaceOne, findOneAndDelete, to'plamni tashlash hamda yumshoq o'chirish naqshi.
Ushbu bo‘lim mundarijasi
O'chirish - qaytarib bo'lmaydigan amal. Shuning uchun bu bobda nafaqat "qanday", balki "qanday xavfsiz" degan savolga ham javob beramiz.
db.kitob.insertMany([
{ _id: 1, nom: "Otkan kunlar", narx: 85000, ombor: 12, janr: "tarixiy" },
{ _id: 2, nom: "Navoiy", narx: 95000, ombor: 8, janr: "tarixiy" },
{ _id: 3, nom: "Ufq", narx: 64000, ombor: 0, janr: "zamonaviy" },
{ _id: 4, nom: "Sarob", narx: 59000, ombor: 0, janr: "ijtimoiy" },
{ _id: 5, nom: "Shum bola", narx: 47000, ombor: 31, janr: "bolalar" }
])
deleteOne #
db.kitob.deleteOne({ _id: 4 })
db.kitob.countDocuments()
{ acknowledged: true, deletedCount: 1 }
4
deleteOne faqat bitta hujjatni o'chiradi - filtr
o'ntasiga mos kelsa ham.
db.kitob.deleteOne({ ombor: 0 })
db.kitob.find({ ombor: 0 }, { nom: 1 })
{ acknowledged: true, deletedCount: 1 }
[ { _id: 4, nom: 'Sarob' } ]
Ikkita kitobning ombori nol edi, lekin faqat bittasi o'chdi.
deleteMany #
db.kitob.deleteMany({ ombor: 0 })
db.kitob.find({}, { nom: 1, ombor: 1 })
{ acknowledged: true, deletedCount: 2 }
[
{ _id: 1, nom: 'Otkan kunlar', ombor: 12 },
{ _id: 2, nom: 'Navoiy', ombor: 8 },
{ _id: 5, nom: 'Shum bola', ombor: 31 }
]
deleteMany({}) - to'plamdagi hamma hujjatni
o'chiradi. Tasdiqlash so'ralmaydi, ogohlantirish
ko'rsatilmaydi.
Bu xato ko'pincha shunday yuz beradi:
const filtr = {}
if (shart) { filtr.janr = "tarixiy" }
db.kitob.deleteMany(filtr)
shart false bo'lsa, filtr bo'sh qoladi va butun to'plam
yo'qoladi.
Uch qavatli himoya:
| Qadam | Nima qilish |
|---|---|
| 1 | Avval countDocuments(filtr) bilan sanang |
| 2 | Keyin find(filtr).limit(5) bilan ko'ring |
| 3 | Shundan keyingina deleteMany(filtr) |
Dasturda esa bo'sh filtrni ochiq taqiqlang:
if (Object.keys(filtr).length === 0) {
throw new Error("Bo'sh filtr bilan o'chirish taqiqlangan")
}
MongoDB da DELETE uchun ROLLBACK yo'q. Tranzaksiya
ichida bo'lmasa, o'chirilgan hujjat faqat zaxira
nusxadan qaytariladi.
Xavfsiz tartibning o'zi:
const filtr = { janr: "tarixiy" }
db.kitob.countDocuments(filtr)
db.kitob.find(filtr, { nom: 1 }).limit(5).toArray()
2
[ { _id: 1, nom: 'Otkan kunlar' }, { _id: 2, nom: 'Navoiy' } ]
Endi nima o'chishini bilamiz - shundan keyin o'chirish mumkin.
replaceOne #
replaceOne hujjatni butunlay yangisi bilan
almashtiradi:
db.kitob.replaceOne({ _id: 5 }, { nom: "Shum bola", narx: 51000 })
db.kitob.findOne({ _id: 5 })
{
acknowledged: true,
insertedId: null,
matchedCount: 1,
modifiedCount: 1,
upsertedCount: 0
}
{ _id: 5, nom: 'Shum bola', narx: 51000 }
ombor va janr maydonlari yo'qoldi - biz ularni yangi
hujjatga yozmadik.
findOneAndDelete #
O'chirilayotgan hujjatning o'zi kerak bo'lsa:
db.kitob.findOneAndDelete(
{ janr: "zamonaviy" },
{ projection: { nom: 1, narx: 1 } }
)
db.kitob.countDocuments({ janr: "zamonaviy" })
{ _id: 3, nom: 'Ufq', narx: 64000 }
0
Bu atomar amal: hujjat topiladi, qaytariladi va o'chiriladi - oraga hech kim tusha olmaydi.
findOneAndDeleteBir nechta ishchi jarayon bitta navbatdan vazifa olayotgan
bo'lsa, find va keyin delete yozish xato:
const vazifa = db.navbat.findOne({ holat: "kutmoqda" })
db.navbat.deleteOne({ _id: vazifa._id })
Ikki jarayon bir vaqtda findOne chaqirsa, ikkalasi
ham bir xil vazifani oladi. Keyin biri o'chiradi,
ikkinchisi esa allaqachon o'chirilgan vazifa ustida ishlaydi.
findOneAndDelete bitta amalda topadi va o'chiradi:
const vazifa = db.navbat.findOneAndDelete({ holat: "kutmoqda" })
Ikkinchi jarayon null oladi va keyingisiga o'tadi. Vazifa
hech qachon ikki marta bajarilmaydi.
Xuddi shu naqsh findOneAndUpdate bilan ham ishlaydi -
vazifani o'chirish o'rniga uni "band" deb belgilash uchun.
To'plamni tashlash #
| Amal | Nima bo'ladi |
|---|---|
deleteMany({}) | Hujjatlar o'chadi, indekslar qoladi |
drop() | To'plam va uning hamma indeksi yo'qoladi |
db.vaqtinchalik.insertMany([{ _id: 1, a: 1 }, { _id: 2, a: 2 }])
db.vaqtinchalik.drop()
db.getCollectionNames().includes("vaqtinchalik")
{ acknowledged: true, insertedIds: { '0': 1, '1': 2 } }
true
false
drop() ancha tezroq: u hujjatlarni birma-bir o'chirmaydi,
balki butun faylni tashlaydi. Million hujjatli to'plamda
farq juda katta.
Yumshoq o'chirish #
Ko'p loyihalarda ma'lumot haqiqatan o'chirilmaydi - faqat "o'chirilgan" deb belgilanadi:
db.kitob.updateOne(
{ _id: 1 },
{ $set: {
ochirilgan: true,
ochirilgan_sana: ISODate("2026-03-15T10:00:00Z")
} }
)
db.kitob.countDocuments({ ochirilgan: { $ne: true } })
db.kitob.find({ ochirilgan: { $ne: true } }, { nom: 1 })
{
acknowledged: true,
insertedId: null,
matchedCount: 1,
modifiedCount: 1,
upsertedCount: 0
}
4
[
{ _id: 2, nom: 'Navoiy' },
{ _id: 3, nom: 'Ufq' },
{ _id: 4, nom: 'Sarob' },
{ _id: 5, nom: 'Shum bola' }
]
Bu naqsh foydali, lekin u bepul emas:
| Muammo | Oqibat |
|---|---|
| Har so'rovga shart qo'shish kerak | Bittasini unutsangiz - o'chirilgan yozuv chiqadi |
| To'plam o'smoqda | Indekslar kattalashadi, so'rov sekinlashadi |
| Yagona indeks buziladi | O'chirilgan yozuv nomni band qilib turadi |
| Shaxsiy ma'lumot qoladi | Talab bo'yicha o'chirish majburiyati bajarilmaydi |
Birinchi muammoni ko'rinish (view) bilan hal qilish mumkin: har doim shu ko'rinishdan o'qing, to'plamdan emas.
Uchinchisi uchun qisman indeks kerak - unique shartni faqat o'chirilmagan yozuvlarga qo'llash.
Oxirgisi esa texnik emas, huquqiy masala. Foydalanuvchi ma'lumotini o'chirish talab qilinsa, uni haqiqatan o'chirish yoki anonimlashtirish kerak.
Amaliy yechim: yumshoq o'chirish + ma'lum muddatdan keyin haqiqiy o'chirish. Buni TTL indeks bilan avtomatlashtirish mumkin - 15-bobda ko'ramiz.
deleteOnebilan bitta hujjatni o'chiring.- Filtrga ikkita hujjat mos kelganda nima bo'lishini sinang.
deleteManybilan shartga mos hammasini o'chiring.deleteMany({})nima qilishini yozing - bajarmang.- O'chirishdan oldingi uch qadamli tekshiruvni bajaring.
replaceOnedan keyin qaysi maydonlar yo'qolganini ko'ring.findOneAndDeletenega navbat uchun to'g'ri ekanini tushuntiring.drop()vadeleteMany({})farqini yozing.- Yumshoq o'chirish qo'shing va so'rovni moslang.
- Yumshoq o'chirishning uchta kamchiligini sanang.
Xulosa #
deleteOnebitta,deleteManyesa hamma mos hujjatni o'chiradi.deleteMany({})butun to'plamni tozalaydi - tasdiqlash so'ralmaydi.- Har doim avval
countDocuments, keyinfind, oxiridadeleteMany. - Dasturda bo'sh filtrni ochiq taqiqlang.
replaceOnebutun hujjatni almashtiradi - yozilmagan maydonlar yo'qoladi._id- almashtirishdan keyin saqlanadigan yagona maydon.findOneAndDeleteatomar - navbat jadvallari uchun to'g'ri tanlov.drop()indekslarni ham o'chiradi va katta to'plamda ancha tezroq.- Yumshoq o'chirish ma'lumotni saqlab qoladi, lekin har so'rovga shart qo'shadi.
- U yagona indeksni buzadi va shaxsiy ma'lumotni saqlab qoladi - buni hisobga oling.
Keyingi bo'limda kursor bilan ishlashni - saralash, cheklash va sahifalashni ko'ramiz.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
Xatolik topdingizmi?
Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.