8-bo‘lim

O'chirish va almashtirish

deleteOne va deleteMany, bo'sh filtr xavfi, replaceOne, findOneAndDelete, to'plamni tashlash hamda yumshoq o'chirish naqshi.

🕑 13 daqiqa o‘qish 📄 638 so‘z 👁 0 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. deleteOne
  2. deleteMany
  3. replaceOne
  4. findOneAndDelete
  5. To'plamni tashlash
  6. Yumshoq o'chirish
  7. Xulosa

O'chirish - qaytarib bo'lmaydigan amal. Shuning uchun bu bobda nafaqat "qanday", balki "qanday xavfsiz" degan savolga ham javob beramiz.

JavaScript
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 #

JavaScript
db.kitob.deleteOne({ _id: 4 })
db.kitob.countDocuments()
Natija
{ acknowledged: true, deletedCount: 1 }
4

deleteOne faqat bitta hujjatni o'chiradi - filtr o'ntasiga mos kelsa ham.

JavaScript
db.kitob.deleteOne({ ombor: 0 })
db.kitob.find({ ombor: 0 }, { nom: 1 })
Natija
{ acknowledged: true, deletedCount: 1 }
[ { _id: 4, nom: 'Sarob' } ]

Ikkita kitobning ombori nol edi, lekin faqat bittasi o'chdi.

deleteMany #

JavaScript
db.kitob.deleteMany({ ombor: 0 })
db.kitob.find({}, { nom: 1, ombor: 1 })
Natija
{ acknowledged: true, deletedCount: 2 }
[
  { _id: 1, nom: 'Otkan kunlar', ombor: 12 },
  { _id: 2, nom: 'Navoiy', ombor: 8 },
  { _id: 5, nom: 'Shum bola', ombor: 31 }
]
Bo'sh filtr butun to'plamni tozalaydi

deleteMany({}) - to'plamdagi hamma hujjatni o'chiradi. Tasdiqlash so'ralmaydi, ogohlantirish ko'rsatilmaydi.

Bu xato ko'pincha shunday yuz beradi:

Natija
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:

QadamNima qilish
1Avval countDocuments(filtr) bilan sanang
2Keyin find(filtr).limit(5) bilan ko'ring
3Shundan keyingina deleteMany(filtr)

Dasturda esa bo'sh filtrni ochiq taqiqlang:

Natija
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:

JavaScript
const filtr = { janr: "tarixiy" }
db.kitob.countDocuments(filtr)
db.kitob.find(filtr, { nom: 1 }).limit(5).toArray()
Natija
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:

JavaScript
db.kitob.replaceOne({ _id: 5 }, { nom: "Shum bola", narx: 51000 })
db.kitob.findOne({ _id: 5 })
Natija
{
  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.

Bir xil ko'rinadi, natija butunlay boshqa updateOne + $set { $set: { narx: 51000 } } nom: saqlanadi ombor: saqlanadi narx: yangilanadi janr: saqlanadi replaceOne { nom: "...", narx: 51000 } nom: yangisidan keladi ombor: YO'QOLADI narx: yangilanadi janr: YO'QOLADI _id - yagona saqlanadigan maydon replaceOne ni faqat butun hujjat qayta qurilayotganda ishlating
Amalda replaceOne kamdan-kam kerak bo'ladi - deyarli har doim $set to'g'riroq

findOneAndDelete #

O'chirilayotgan hujjatning o'zi kerak bo'lsa:

JavaScript
db.kitob.findOneAndDelete(
  { janr: "zamonaviy" },
  { projection: { nom: 1, narx: 1 } }
)
db.kitob.countDocuments({ janr: "zamonaviy" })
Natija
{ _id: 3, nom: 'Ufq', narx: 64000 }
0

Bu atomar amal: hujjat topiladi, qaytariladi va o'chiriladi - oraga hech kim tusha olmaydi.

Navbat jadvali uchun findOneAndDelete

Bir nechta ishchi jarayon bitta navbatdan vazifa olayotgan bo'lsa, find va keyin delete yozish xato:

Natija
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:

Natija
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 #

AmalNima bo'ladi
deleteMany({})Hujjatlar o'chadi, indekslar qoladi
drop()To'plam va uning hamma indeksi yo'qoladi
JavaScript
db.vaqtinchalik.insertMany([{ _id: 1, a: 1 }, { _id: 2, a: 2 }])
db.vaqtinchalik.drop()
db.getCollectionNames().includes("vaqtinchalik")
Natija
{ 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:

JavaScript
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 })
Natija
{
  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' }
]
Yumshoq o'chirishning yashirin narxi

Bu naqsh foydali, lekin u bepul emas:

MuammoOqibat
Har so'rovga shart qo'shish kerakBittasini unutsangiz - o'chirilgan yozuv chiqadi
To'plam o'smoqdaIndekslar kattalashadi, so'rov sekinlashadi
Yagona indeks buziladiO'chirilgan yozuv nomni band qilib turadi
Shaxsiy ma'lumot qoladiTalab 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.

Amaliy topshiriq
  1. deleteOne bilan bitta hujjatni o'chiring.
  2. Filtrga ikkita hujjat mos kelganda nima bo'lishini sinang.
  3. deleteMany bilan shartga mos hammasini o'chiring.
  4. deleteMany({}) nima qilishini yozing - bajarmang.
  5. O'chirishdan oldingi uch qadamli tekshiruvni bajaring.
  6. replaceOne dan keyin qaysi maydonlar yo'qolganini ko'ring.
  7. findOneAndDelete nega navbat uchun to'g'ri ekanini tushuntiring.
  8. drop() va deleteMany({}) farqini yozing.
  9. Yumshoq o'chirish qo'shing va so'rovni moslang.
  10. Yumshoq o'chirishning uchta kamchiligini sanang.

Xulosa #

  • deleteOne bitta, deleteMany esa hamma mos hujjatni o'chiradi.
  • deleteMany({}) butun to'plamni tozalaydi - tasdiqlash so'ralmaydi.
  • Har doim avval countDocuments, keyin find, oxirida deleteMany.
  • Dasturda bo'sh filtrni ochiq taqiqlang.
  • replaceOne butun hujjatni almashtiradi - yozilmagan maydonlar yo'qoladi.
  • _id - almashtirishdan keyin saqlanadigan yagona maydon.
  • findOneAndDelete atomar - 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.

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.