MongoDB hujjat yangilash: updateOne va $set

Mahsulot narxi o’zgardi, buyurtma holati “yuborildi” ga o’tdi, omborda soni kamaydi. Bularning har biri mavjud hujjatni o’zgartirishni talab qiladi.

MongoDB’da yangilashning o’z qoidasi bor va u birinchi marta adashtiradi: hujjatni butunlay almashtirish va bir maydonini o’zgartirish ikki xil yozuv.

Misollar uchun baza:

use shop
db.products.drop()
db.products.insertMany([
  { name: "O'tkan kunlar", category: "kitob", price: 45000, quantity: 12 },
  { name: "Mehrobdan chayon", category: "kitob", price: 38000, quantity: 7 },
  { name: "Shum bola", category: "kitob", price: 29000, quantity: 0 },
  { name: "Daftar", category: "kanselyariya", price: 8000, quantity: 150 },
  { name: "Ruchka", category: "kanselyariya", price: 4000, quantity: 300 }
])
{
  acknowledged: true,
  insertedIds: {
    '0': ObjectId('671f8a1b2c3d4e5f6a7b8c31'),
    '1': ObjectId('671f8a1b2c3d4e5f6a7b8c32'),
    '2': ObjectId('671f8a1b2c3d4e5f6a7b8c33'),
    '3': ObjectId('671f8a1b2c3d4e5f6a7b8c34'),
    '4': ObjectId('671f8a1b2c3d4e5f6a7b8c35')
  }
}

updateOne va $set

Yangilash ikki qismdan iborat: filtr (kimni) va o’zgarish (nima qilish).

db.products.updateOne(
  { name: "Daftar" },
  { $set: { price: 9500 } }
)
{
  acknowledged: true,
  insertedId: null,
  matchedCount: 1,
  modifiedCount: 1,
  upsertedCount: 0
}

Natijani tekshiramiz:

db.products.findOne({ name: "Daftar" }, { name: 1, price: 1, _id: 0 })
{ name: 'Daftar', price: 9500 }

Bir vaqtda bir necha maydon:

db.products.updateOne(
  { name: "Ruchka" },
  { $set: { price: 4500, quantity: 280, updatedAt: new Date() } }
)
{
  acknowledged: true,
  insertedId: null,
  matchedCount: 1,
  modifiedCount: 1,
  upsertedCount: 0
}

updatedAt maydoni hujjatda yo’q edi — $set uni qo’shib qo’ydi. Mavjud maydonni o’zgartirish va yangisini qo’shish bir xil yoziladi.

Natija obyektini o’qish

Uchta son qaytadi va ular boshqa-boshqa narsani bildiradi:

Maydon Ma’nosi
matchedCount Filtrga mos kelgan hujjatlar soni
modifiedCount Haqiqatan o’zgargan hujjatlar soni
upsertedCount Yangi yaratilgan hujjatlar soni

Ular har doim ham teng bo’lmaydi:

db.products.updateOne(
  { name: "Daftar" },
  { $set: { price: 9500 } }
)
{
  acknowledged: true,
  insertedId: null,
  matchedCount: 1,
  modifiedCount: 0,
  upsertedCount: 0
}

Hujjat topildi, lekin narx allaqachon 9500 edi — o’zgarish bo’lmadi.

$set siz yozish — butun hujjatni almashtirish

Bu darsning eng muhim tuzog’i:

db.products.replaceOne(
  { name: "Shum bola" },
  { name: "Shum bola", price: 31000 }
)
{
  acknowledged: true,
  insertedId: null,
  matchedCount: 1,
  modifiedCount: 1,
  upsertedCount: 0
}
db.products.findOne({ name: "Shum bola" })
{
  _id: ObjectId('671f8a1b2c3d4e5f6a7b8c33'),
  name: 'Shum bola',
  price: 31000
}

category va quantity maydonlari yo’qoldi. replaceOne hujjatni butunlay yangisiga almashtiradi.

$inc — sonni oshirish va kamaytirish

Omborda soni bittaga kamaydi. Hozirgi qiymatni o’qib, bittani ayirib, qaytadan yozish mumkin edi — lekin ikki foydalanuvchi bir vaqtda shunday qilsa, bittasining o’zgarishi yo’qoladi.

$inc bu ishni bazaning o’zida bajaradi:

db.products.updateOne(
  { name: "Daftar" },
  { $inc: { quantity: -1 } }
)
{
  acknowledged: true,
  insertedId: null,
  matchedCount: 1,
  modifiedCount: 1,
  upsertedCount: 0
}
db.products.findOne({ name: "Daftar" }, { name: 1, quantity: 1, _id: 0 })
{ name: 'Daftar', quantity: 149 }

Musbat son oshiradi:

db.products.updateOne(
  { name: "Daftar" },
  { $inc: { quantity: 50, viewCount: 1 } }
)
{
  acknowledged: true,
  insertedId: null,
  matchedCount: 1,
  modifiedCount: 1,
  upsertedCount: 0
}
db.products.findOne({ name: "Daftar" }, { name: 1, quantity: 1, viewCount: 1, _id: 0 })
{ name: 'Daftar', quantity: 199, viewCount: 1 }

viewCount maydoni yo’q edi — $inc uni 0 deb hisoblab, 1 qilib yaratdi.

updateMany — bir necha hujjat

updateOne filtrga mos birinchi hujjatni yangilaydi. Hammasini o’zgartirish uchun updateMany:

db.products.updateMany(
  { category: "kitob" },
  { $set: { discount: 10 } }
)
{
  acknowledged: true,
  insertedId: null,
  matchedCount: 3,
  modifiedCount: 3,
  upsertedCount: 0
}
db.products.find({ category: "kitob" }, { name: 1, discount: 1, _id: 0 })
[
  { name: "O'tkan kunlar", discount: 10 },
  { name: 'Mehrobdan chayon', discount: 10 },
  { name: 'Shum bola', discount: 10 }
]

Narxlarni 10 foizga oshirish:

db.products.updateMany(
  { category: "kanselyariya" },
  { $mul: { price: 1.1 } }
)
{
  acknowledged: true,
  insertedId: null,
  matchedCount: 2,
  modifiedCount: 2,
  upsertedCount: 0
}
db.products.find({ category: "kanselyariya" }, { name: 1, price: 1, _id: 0 })
[
  { name: 'Daftar', price: 10450.000000000002 },
  { name: 'Ruchka', price: 4950.000000000001 }
]

$unset va $rename

Maydonni butunlay olib tashlash:

db.products.updateMany(
  { category: "kitob" },
  { $unset: { discount: "" } }
)
{
  acknowledged: true,
  insertedId: null,
  matchedCount: 3,
  modifiedCount: 3,
  upsertedCount: 0
}
db.products.findOne({ name: "O'tkan kunlar" }, { name: 1, discount: 1, _id: 0 })
{ name: "O'tkan kunlar" }

$unset dagi "" qiymati ishlatilmaydi — sintaksis shuni talab qiladi, o’rniga nima yozilishi ahamiyatsiz.

Maydon nomini o’zgartirish:

db.products.updateMany({}, { $rename: { quantity: "stockCount" } })
{
  acknowledged: true,
  insertedId: null,
  matchedCount: 5,
  modifiedCount: 5,
  upsertedCount: 0
}
db.products.findOne({ name: "Ruchka" }, { name: 1, stockCount: 1, _id: 0 })
{ name: 'Ruchka', stockCount: 280 }

Bu — SQL’dagi ALTER TABLE ning MongoDB muqobili. Farqi: bu yerda hujjatlar birma-bir yangilanadi, jadval tuzilishi o’zgarmaydi.

Nomni orqaga qaytaramiz, keyingi misollar uchun:

db.products.updateMany({}, { $rename: { stockCount: "quantity" } })
{
  acknowledged: true,
  insertedId: null,
  matchedCount: 5,
  modifiedCount: 5,
  upsertedCount: 0
}

upsert — yo’q bo’lsa yarat

Ba’zan “bor bo’lsa yangila, yo’q bo’lsa qo’sh” kerak bo’ladi. Ikki buyruq yozish o’rniga upsert bayrog’i qo’yiladi:

db.products.updateOne(
  { name: "Markerlar" },
  { $set: { category: "kanselyariya", price: 15000, quantity: 40 } },
  { upsert: true }
)
{
  acknowledged: true,
  insertedId: ObjectId('671f8b2c3d4e5f6a7b8c9d36'),
  matchedCount: 0,
  modifiedCount: 0,
  upsertedCount: 1
}

matchedCount: 0 — topilmadi, upsertedCount: 1 — yaratildi. Yangi hujjatga filtrdagi name ham qo’shildi:

db.products.findOne({ name: "Markerlar" }, { _id: 0 })
{ name: 'Markerlar', category: 'kanselyariya', price: 15000, quantity: 40 }

Shu buyruqni takrorlasangiz, endi yangilanish bo’ladi:

db.products.updateOne(
  { name: "Markerlar" },
  { $set: { price: 16000 } },
  { upsert: true }
)
{
  acknowledged: true,
  insertedId: null,
  matchedCount: 1,
  modifiedCount: 1,
  upsertedCount: 0
}

Amaliy mashq

Yuqoridagi shop bazasida bajaring:

  1. updateOne va $set bilan bitta mahsulot narxini o’zgartiring va matchedCount hamda modifiedCount ni solishtiring.
  2. Xuddi shu buyruqni ikkinchi marta yurgizing — modifiedCount nega 0 bo’lganini tushuntiring.
  3. Mavjud bo’lmagan nom bilan updateOne chaqiring va xato chiqmasligiga ishonch hosil qiling.
  4. $inc bilan bitta mahsulot quantity sini -3 ga o’zgartiring, so’ng mavjud bo’lmagan soldCount maydonini $inc bilan oshiring.
  5. updateMany bilan butun kategoriyaga isFeatured: false maydonini qo’shing, keyin $unset bilan uni olib tashlang.
  6. upsert: true bilan yangi mahsulot yarating va shu buyruqni takrorlab, upsertedCount dan modifiedCount ga o’tishni kuzating.

3-qadam eng ko’p sezilmay qoladigan xatoni ko’rsatadi: yangilanmagan hujjat ham “muvaffaqiyatli” javob qaytaradi.

Qisqacha xulosa

  • updateOne bitta, updateMany barcha mos hujjatlarni yangilaydi.
  • O’zgarish har doim operator bilan yoziladi — eng ko’p ishlatilgani $set.
  • $set mavjud maydonni o’zgartiradi, bo’lmaganini qo’shadi; replaceOne esa hujjatni butunlay almashtiradi.
  • matchedCount topilganni, modifiedCount haqiqatan o’zgarganni bildiradi; filtr bo’sh qaytsa ham xato chiqmaydi.
  • $inc sonni bazaning o’zida atomar oshiradi, $mul ko’paytiradi.
  • $unset maydonni o’chiradi, $rename nomini o’zgartiradi.
  • upsert: true topilmasa yangi hujjat yaratadi — filtri yagona maydon bo’yicha bo’lsin.

Keyingi darsda hujjat o’chirishdeleteOne, deleteMany va o’chirishdagi xavfsizlik.

Bu dars foydali bo'ldimi?

marta ko'rildi