4-bo‘lim
Hujjat qo'shish
insertOne va insertMany, _id ni o'zi berish yoki avtomatik qoldirish, takroriy kalit xatosi, ordered va yozuv kafolati.
Ushbu bo‘lim mundarijasi
Hujjat qo'shish MongoDB dagi eng oddiy amal. Lekin uning ichida bir nechta muhim tafsilot bor: kalit qayerdan keladi, xato bo'lsa nima bo'ladi va yozuv qachon "saqlandi" hisoblanadi.
db.kitob.insertMany([
{ _id: 1, nom: "Otkan kunlar", muallif: "Abdulla Qodiriy", narx: 85000 },
{ _id: 2, nom: "Navoiy", muallif: "Oybek", narx: 95000 },
{ _id: 3, nom: "Ufq", muallif: "Said Ahmad", narx: 64000 }
])
insertOne #
db.kitob.insertOne({
_id: 4,
nom: "Kecha va kunduz",
muallif: "Cho'lpon",
narx: 68000
})
{ acknowledged: true, insertedId: 4 }
Javobda ikkita maydon bor:
| Maydon | Ma'nosi |
|---|---|
acknowledged | Server yozuvni tasdiqladimi |
insertedId | Qo'shilgan hujjatning kaliti |
insertMany #
db.kitob.insertMany([
{ _id: 5, nom: "Sarob", muallif: "Abdulla Qahhor", narx: 59000 },
{ _id: 6, nom: "Shum bola", muallif: "G'afur G'ulom", narx: 47000 }
])
db.kitob.countDocuments()
{ acknowledged: true, insertedIds: { '0': 5, '1': 6 } }
5
_id ni o'zingiz bering yoki qoldiring #
_id majburiy, lekin uni yozish shart emas:
const javob = db.kitob.insertOne({ nom: "Yulduzli tunlar", narx: 78000 })
javob.acknowledged
javob.insertedId instanceof ObjectId
db.kitob.findOne({ nom: "Yulduzli tunlar" }).narx
true
true
78000
Biz _id bermadik, MongoDB esa ObjectId qo'ydi.
_id ingizni qo'yish ko'pincha yaxshiroqAgar ma'lumotning tabiiy kaliti bo'lsa - ISBN, pasport
raqami, tartib raqami - uni to'g'ridan-to'g'ri _id ga
qo'ying.
| Yondashuv | Yutuq |
|---|---|
_id: "978-9943-01-234-5" | Qidirish uchun qo'shimcha indeks kerak emas |
_id: ObjectId(...) + isbn maydoni | Ikkita indeks, ikki baravar joy |
_id bo'yicha indeks baribir mavjud va u yagona.
Tabiiy kalitni shu yerga qo'ysangiz, takrorlanishdan
himoya ham bepul keladi.
Faqat bitta shart: _id ni keyinchalik o'zgartirib
bo'lmaydi. Shuning uchun u haqiqatan o'zgarmas
bo'lishiga ishonch hosil qiling. Masalan elektron pochta
manzili yomon tanlov - odam uni almashtirishi mumkin.
Takroriy kalit #
db.kitob.insertOne({ _id: 1, nom: "Boshqa kitob" })
MongoServerError: E11000 duplicate key error collection: dokon.kitob index: _id_ dup key: { _id: 1 }
E11000 - MongoDB dagi eng ko'p uchraydigan xato kodi.
U "bu kalit allaqachon band" degani.
ordered - xato bo'lganda to'xtaymizmi #
insertMany odatda tartibli ishlaydi: birinchi xatoda
to'xtaydi va qolganini qo'shmaydi.
db.kitob.insertMany([
{ _id: 10, nom: "Birinchi" },
{ _id: 1, nom: "Takror - bu xato" },
{ _id: 11, nom: "Uchinchi" }
])
db.kitob.find({ _id: { $in: [10, 11] } }, { nom: 1 })
Uncaught:
MongoBulkWriteError: E11000 duplicate key error collection: dokon.kitob index: _id_ dup key: { _id: 1 }
Result: BulkWriteResult {
insertedCount: 1,
matchedCount: 0,
modifiedCount: 0,
deletedCount: 0,
upsertedCount: 0,
upsertedIds: {},
insertedIds: { '0': 10 }
}
Write Errors: [
WriteError {
err: {
index: 1,
code: 11000,
errmsg: 'E11000 duplicate key error collection: dokon.kitob index: _id_ dup key: { _id: 1 }',
errInfo: undefined,
op: { _id: 1, nom: 'Takror - bu xato' }
}
}
]
[ { _id: 10, nom: 'Birinchi' } ]
_id: 10 qo'shildi, lekin _id: 11 qo'shilmadi - xatodan
keyin ish to'xtadi.
Endi ordered: false bilan:
db.kitob.insertMany([
{ _id: 10, nom: "Birinchi" },
{ _id: 1, nom: "Takror - bu xato" },
{ _id: 11, nom: "Uchinchi" }
], { ordered: false })
db.kitob.find({ _id: { $in: [10, 11] } }, { nom: 1 })
Uncaught:
MongoBulkWriteError: E11000 duplicate key error collection: dokon.kitob index: _id_ dup key: { _id: 1 }
Result: BulkWriteResult {
insertedCount: 2,
matchedCount: 0,
modifiedCount: 0,
deletedCount: 0,
upsertedCount: 0,
upsertedIds: {},
insertedIds: { '0': 10, '2': 11 }
}
Write Errors: [
WriteError {
err: {
index: 1,
code: 11000,
errmsg: 'E11000 duplicate key error collection: dokon.kitob index: _id_ dup key: { _id: 1 }',
errInfo: undefined,
op: { _id: 1, nom: 'Takror - bu xato' }
}
}
]
[ { _id: 10, nom: 'Birinchi' }, { _id: 11, nom: 'Uchinchi' } ]
Xato baribir chiqdi, lekin bu safar ikkala yaxshi hujjat ham qo'shildi.
insertMany - bu tranzaksiya emasEng xavfli noto'g'ri tasavvur: "insertMany yo hammasini
qo'shadi, yo hech birini".
Bu noto'g'ri. Yuqoridagi natijaning o'zi buni ko'rsatdi: birinchi holatda bitta hujjat qo'shilib qoldi.
| Rejim | Xatodan keyin | Undan oldingilar |
|---|---|---|
ordered: true (odatiy) | To'xtaydi | Qo'shilgan holicha qoladi |
ordered: false | Davom etadi | Qo'shiladi |
Haqiqiy "yo hammasi, yo hech nima" kerak bo'lsa, tranzaksiya ishlatiladi - 17-bobda ko'ramiz.
ordered: false qachon foydali: ma'lumotni ko'chirib
o'tkazayotganda va bir nechta yozuv takror bo'lishi
mumkinligini bilganda. Shunda ish to'xtamaydi.
Yozuv kafolati #
acknowledged: true "diskka yozildi" degani emas. U
"server buyruqni qabul qildi" degani.
Aniq kafolatni writeConcern belgilaydi:
| Yozuv | Ma'nosi |
|---|---|
w: 1 | Asosiy server qabul qildi (odatiy) |
w: "majority" | Nusxalarning ko'pchiligi qabul qildi |
j: true | Jurnalga (diskka) yozildi |
w: 0 | Javob kutilmaydi - eng tez, eng ishonchsiz |
db.kitob.insertOne(
{ _id: 20, nom: "Muhim yozuv", narx: 100000 },
{ writeConcern: { w: "majority", j: true } }
)
{ acknowledged: true, insertedId: 20 }
w: 0 - javobsiz yozuvw: 0 bilan mijoz serverning javobini umuman kutmaydi.
Buyruq yuboriladi va dastur darhol keyingi qatorga o'tadi.
Bu tez, lekin quyidagilarni bilmay qolasiz:
- yozuv haqiqatan bordimi;
- takroriy kalit xatosi bo'ldimi;
- server umuman ishlayaptimi.
Bu rejim faqat yo'qolishi mumkin bo'lgan ma'lumot uchun o'rinli: sahifa ko'rishlari hisoblagichi, ixtiyoriy telemetriya.
Buyurtma, to'lov yoki foydalanuvchi ro'yxati uchun esa
kamida w: "majority" kerak. Aks holda asosiy server
almashganda yozuv yo'qolishi mumkin.
Boshqa qo'shish usullari #
| Usul | Nima qiladi |
|---|---|
insertOne | Bitta hujjat |
insertMany | Ro'yxat |
updateOne + upsert: true | Yo'q bo'lsa qo'shadi, bor bo'lsa yangilaydi |
bulkWrite | Bir nechta har xil amalni birga |
mongoimport | Fayldan (JSON, CSV) - 19-bob |
const javob = db.kitob.updateOne(
{ nom: "Mehrobdan chayon" },
{ $set: { muallif: "Abdulla Qodiriy", narx: 72000 } },
{ upsert: true }
)
javob.matchedCount
javob.upsertedCount
db.kitob.findOne({ nom: "Mehrobdan chayon" }, { _id: 0 })
0
1
{ nom: 'Mehrobdan chayon', muallif: 'Abdulla Qodiriy', narx: 72000 }
matchedCount: 0 - mos hujjat topilmadi. upsertedCount: 1
- shuning uchun yangisi yaratildi. Filtrdagi
nomham yangi
hujjatga tushib qolganiga e'tibor bering.
upsert haqida 7-bobda batafsil gaplashamiz.
insertOnebilan bitta hujjat qo'shing va javobni o'qing.insertManybilan uchta hujjat qo'shing._idbermasdan hujjat qo'shing va nima qo'yilganini ko'ring.- Tabiiy kalitni
_idga qo'yishning foydasini yozing. _iduchun elektron pochta nega yomon tanlov ekanini tushuntiring.- Takroriy
_idbilan hujjat qo'shib, xato kodini yozing. ordered: trueda xatodan keyin nima bo'lishini sinang.- Xuddi shuni
ordered: falsebilan takrorlang va farqni yozing. insertManynega tranzaksiya emasligini tushuntiring.w: "majority"qachon kerakligini yozing.
Xulosa #
insertOnebitta,insertManybir nechta hujjat qo'shadi._idmajburiy; berilmasa mijozObjectIdyaratadi.ObjectIdni server emas, mijoz yaratadi - shuning uchun u darhol ma'lum.- Tabiiy kalit bo'lsa (ISBN, tartib raqami), uni to'g'ridan-to'g'ri
_idga qo'ying. _idni keyin o'zgartirib bo'lmaydi - o'zgaruvchan qiymatni qo'ymang.- Takroriy kalit E11000 xatosini beradi.
insertManytranzaksiya emas: xatodan oldin qo'shilganlar joyida qoladi.ordered: falsexatodan keyin ham davom etadi.acknowledged: true"diskka yozildi" degani emas.- Muhim ma'lumot uchun
w: "majority", yo'qolsa mayli bo'lgan uchunw: 0.
Keyingi bo'limda hujjatlarni qidirishni - find va filtr
operatorlarini 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.