IlmHamroh
JavaScript Full-stack/27-qism. Ma'lumotlar bazasi chuqur: Postgres, ORM, Mongo, Redis42/65-dars17 daqiqa
Mundarija (28)

MongoDB nima: hujjat, kolleksiya, BSON va ObjectId — tuzilishi va vositalari

Qisqacha: MongoDB ma'lumotni jadval qatorlarida emas, hujjatlarda saqlaydi. Hujjat — JSON'ga o'xshash obyekt, ichida massiv va ichma-ich obyektlar bo'lishi mumkin. Tuzilma uch qavatli: baza → kolleksiya → hujjat. Diskda hujjat BSON (ikkilik JSON) bo'lib yotadi, u sana, ObjectId va aniq son turlarini ham biladi. Har hujjatda _id bor; sukut bo'yicha u ObjectId — 12 bayt, birinchi 4 bayti yaratilgan vaqt. Kolleksiya sxemani tekshirmaydi: kanonda bir xil kolleksiyaga matn: 42 ham jim kirdi.

Bu darsda

  • Postgres'dagi to'rt jadvallik vazifani Mongo'da bitta hujjat sifatida o'qiysiz.
  • Baza, kolleksiya va hujjat qanday bog'langanini tushuntira olasiz.
  • BSON JSON'dan nimasi bilan farq qilishini va _id/ObjectId ichida nima borligini bilasiz.
  • ObjectId'dan yaratilgan vaqtni o'zingiz chiqarasiz.
  • mongosh bilan bazani ko'rasiz va sxemasizlikning narxini kanon misolida ko'rasiz.

Oldin bilishingiz kerak: DB turlari xaritasi va SQL vs NoSQL, Volume va bind mount, JSONB, Relatsion model.

1. Nega bu kerak?

DB turlari xaritasi darsida bazalarni turlarga ajratdik. U yerda hujjat (document) baza haqida bir paragraf bor edi: "vazifa va uning egasi bitta hujjatda, ichma-ich". Endi shu turning eng mashhurini — MongoDB ni ochib ko'ramiz.

vazifalar ilovasida bitta vazifani ekranga chiqarish uchun Postgres'da to'rt jadvalga murojaat qilamiz: vazifalar, izohlar, vazifa_teglari, teglar. Keyin JOIN yoki json_agg bilan ularni yig'amiz (N+1 muammosi darsidagi "bitta so'rov").

O'xshatish: kutubxonada kitob haqidagi ma'lumot to'rt shkafda saqlansa — bittasida nomi, boshqasida o'quvchilar sharhi, uchinchisida yorliqlari. Kerak bo'lganda to'rt shkafdan yig'asiz. Hujjat baza esa hamma narsani bitta papkaga solib qo'yadi: papkani oldingiz — hammasi qo'lingizda.

Bu yaxshimi? Ba'zan ha, ba'zan yo'q. Bu qismning 11 ta darsi shu savolga o'lchov bilan javob beradi. Avval asosini ko'ramiz: MongoDB ichida nima bor va qanday vositalar bilan ishlaymiz.

Maslahat: Bu darslarda vazifalar-api Mongo'ga ko'chmaydi — u Postgres'da qoladi. Mongo'ni taqqoslash va alohida bilim sifatida o'rganamiz. Kanon Postgres'dagi o'sha namunani (8 foydalanuvchi, 48 vazifa) Mongo'ga ko'chirdi, shuning uchun natijalarni ikki baza o'rtasida solishtirish mumkin.

2. Hujjat modeli: baza → kolleksiya → hujjat

2.1 Uch qavat

MongoDB serveri ichida bir nechta baza (database) bo'ladi. Har bazada kolleksiyalar (collection) — bir turdagi hujjatlar guruhi. Har kolleksiyada hujjatlar (document).

flowchart TD
  S["MongoDB serveri"] --> B1["baza: vazifalar"]
  S --> B2["baza: admin"]
  B1 --> K1["kolleksiya: vazifalar"]
  B1 --> K2["kolleksiya: foydalanuvchilar"]
  K1 --> H1["hujjat: pgId 1"]
  K1 --> H2["hujjat: pgId 2"]
  K2 --> H3["hujjat: Aziz"]

Diagrammaga qarang: Postgres'dagi "baza → jadval → qator" ga juda o'xshaydi. Farqi — eng pastki qavatda. Qator — tekis, har ustunda bitta qiymat. Hujjat — daraxt: ichida massiv, massiv ichida obyekt bo'lishi mumkin.

Postgres MongoDB Farqi
baza baza bir xil g'oya
jadval kolleksiya kolleksiya ustunlarni bilmaydi
qator hujjat hujjat ichma-ich bo'la oladi
birlamchi kalit _id har hujjatda majburiy

Kolleksiya oldindan yaratilmaydi. Birinchi hujjat yozilganda Mongo uni o'zi ochadi. Baza ham shunday. CREATE TABLE ning to'g'ridan-to'g'ri o'xshashi yo'q.

2.2 Kanondagi vazifa hujjati

Kanon Postgres holat 11 namunasini Mongo'ga ko'chirdi (ko'chirish kodi — keyingi darsda). Teglar va izohlar vazifaning ichiga joylandi, egasi esa foydalanuvchilar kolleksiyasiga ishora qiladi. Mana 1-vazifa — drayver findOne bilan olib, JSON qilib chop etgan (Node 24.21.0, mongodb 7.7.0, MongoDB 8.3.13; kanon chiqishi 700 belgida kesilgan, biz uni izohlar boshida to'xtatdik):

text
{
 "_id": "6add9a837ffcaf2b9d405510",
 "pgId": 1,
 "egasi": "6add9a837ffcaf2b9d405508",
 "matn": "JavaScript kursining 26-qismini boshlash #o'qish",
 "bajarildi": false,
 "ustuvorlik": "yuqori",
 "muddat": "2026-10-31T18:59:00.000Z",
 "yaratilgan": "2026-10-01T03:30:00.000Z",
 "tartib": 1,
 "versiya": 1,
 "teglar": [
  "o'qish"
 ],
 "izohlar": [
  {
   "muallif": "6add9a837ffcaf2b9d405508",
   "matn": "Docker darslaridan boshladim",
   "yaratilgan": "2026-10-01T15:00:00.000Z"
  },

Nimaga qarang:

  • teglar — oddiy satrlar massivi. Postgres'da bu vazifa_teglari + teglar jadvallari edi.
  • izohlar — obyektlar massivi. Postgres'da alohida izohlar jadvali.
  • egasi — boshqa hujjatning _id si. Bu ishora (reference): Postgres'dagi tashqi kalitga o'xshaydi, lekin baza uni tekshirmaydi.
  • pgId — kanon Postgres'dagi id'ni saqlab qo'ydi, solishtirish uchun.

Hujjat ichiga joylash — embed, boshqa hujjatga ishora qilish — reference. Qachon qaysi biri — Populate va embed vs reference darsining asosiy savoli.

Tekshirib ko'ring: Postgres'da 1-vazifani teglari va izohlari bilan olish uchun nechta jadvalga murojaat kerak? Mongo'da-chi?

Javob

Postgres'da to'rtta: vazifalar, izohlar, vazifa_teglari, teglar (JOIN yoki ichki so'rovlar bilan). Mongo'da — bitta hujjat, bitta findOne. Lekin izohlar muallifining ismi kerak bo'lsa, Mongo'da ham foydalanuvchilar ga ikkinchi murojaat kerak: hujjatda faqat muallif _id si bor.

3. BSON: diskdagi hujjat

3.1 Nega oddiy JSON emas

JSON'da atigi oltita tur bor: satr, son, mantiqiy, null, massiv, obyekt. Sana yo'q — sana satr bo'lib yoziladi. Son bitta — butun va kasr farqi yo'q.

MongoDB hujjatni BSON (Binary JSON) formatida saqlaydi. U ikkilik (binary) format: diskda va tarmoqda ixcham, tez o'qiladi va JSON'dan ko'proq tur biladi:

BSON turi Misol Nega kerak
Date ISODate('2026-10-01T03:30:00.000Z') sana sana bo'lib saqlanadi, satr emas
ObjectId ObjectId('6add9a83…') 12 baytli noyob id
int32 / int64 / double 1, NumberLong(…), 0.5 butun va kasr sonlar farqlanadi
Decimal128 NumberDecimal('35000.00') pul uchun aniq kasr
Binary rasm, hash bayti baytlar to'g'ridan

Chiqishda "yaratilgan": "2026-10-01T03:30:00.000Z" satrga o'xshaydi. Bu JSON.stringify ning ishi. Aslida Node'ga Date keldi — kanon shuni alohida tekshirdi:

text
_id: 6add9a837ffcaf2b9d405510 | ichidagi vaqt: 2026-10-25T05:58:27.000Z | turi: object true
hujjat hajmi (BSON): 258 bayt o'rtacha; to'plam: 12403 bayt

turi: object true — typeof "object" va instanceof Date true. Ya'ni Postgres'dagi timestamptz Mongo'da haqiqiy sana bo'lib qoldi. Vazifa hujjati o'rtacha 258 bayt, 48 ta hujjatli kolleksiya — 12 403 bayt (kanon chiqishida "to'plam" — kolleksiyaning o'zbekcha nomi).

3.2 16 MB chegara

Bitta BSON hujjatning maksimal hajmi — 16 MB. 258 baytli vazifa uchun bu juda katta zaxira. Lekin hujjat ichidagi massiv cheksiz o'saversa (masalan, 100 000 izoh), chegaraga yetadi. Bu "cheksiz massiv" anti-naqshini sxema dizayn naqshlari darsida o'lchaymiz.

4. _id va ObjectId

4.1 _id majburiy

Har hujjatda _id maydoni bor va u kolleksiya ichida noyob. Siz bermasangiz — drayver o'zi ObjectId yaratib qo'yadi. Istasangiz o'zingiz berasiz: son, satr, hatto obyekt. Kanonning katta to'plamida _id — Postgres'dagi son id (_id: 1, _id: 2, …).

_id bo'yicha indeks doim bor, uni o'chirib bo'lmaydi.

4.2 ObjectId ichida nima bor

ObjectId — 12 bayt, ekranda 24 ta o'n oltilik belgi:

text
6add9a83  7ffcaf2b9d  405510
└ vaqt ┘  └tasodifiy┘ └hisob┘
 4 bayt     5 bayt    3 bayt
  • 4 bayt — vaqt: Unix soniyalari (1970-yildan beri), hujjat yaratilgan payt.
  • 5 bayt — tasodifiy qiymat: har jarayon uchun bir marta tanlanadi.
  • 3 bayt — hisoblagich: har yangi ObjectId'da bittaga oshadi.

Shu tuzilma tufayli ObjectId'ni bazaga so'ramasdan yaratish mumkin — drayver o'zi yasaydi va ikki mashinada ham takrorlanish ehtimoli juda kichik. Bonus: ObjectId'lar vaqt bo'yicha o'sib boradi, _id bo'yicha saralash taxminan "yaratilgan tartibi" ni beradi (bir soniya ichida aniq emas).

Vaqtni o'zimiz chiqarib ko'ramiz. Brauzerda ham ishlaydi:

js
// ObjectId — 24 belgi; birinchi 8 tasi — vaqt (soniya)
const id = "6add9a837ffcaf2b9d405510";
const soniya = parseInt(id.slice(0, 8), 16);
console.log(soniya); // 1792907907
console.log(new Date(soniya * 1000).toISOString());
// 2026-10-25T05:58:27.000Z

mongosh'dagi getTimestamp() aynan shu ishni qiladi. Kanon chiqishi (MongoDB 8.3.13, mongosh 2.13.0):

js
const id = db.vazifalar.findOne({pgId: 1})._id;
printjson({hex: id.toHexString(), vaqt: id.getTimestamp()})
text
{
  hex: '6add9a837ffcaf2b9d405510',
  vaqt: ISODate('2026-10-25T05:58:27.000Z')
}

Bizning hisob bilan bir xil. Endi muhim kuzatuv: vazifaning o'z yaratilgan maydoni — 2026-10-01T03:30:00Z, ObjectId vaqti esa 2026-10-25T05:58:27Z. Nega farq?

ObjectId vaqti — hujjat Mongo'ga yozilgan payt, ya'ni kanon ko'chirish skriptini ishga tushirgan soniya. Vazifa esa Postgres'da ancha oldin yaratilgan. Shuning uchun ObjectId vaqtini biznes sana (vazifa qachon qo'shilgan) sifatida ishlatmang — ko'chirish, import yoki tiklashdan keyin u yolg'on gapiradi. Sanani alohida maydonda saqlang.

Diqqat: Darsdagi ObjectId'lar (6add9a83…) kanon mashinasida yaratilgan. Siz o'zingizda ishga tushirsangiz, boshqa qiymat chiqadi — ObjectId va undagi vaqt deterministik emas. Shuning uchun keyingi darslarda chiqishdagi id'larga e'tibor bermang, tuzilmasiga qarang.

Tekshirib ko'ring: Ikki hujjatning _id si 6add9a83… va 6add9a84… bilan boshlanadi. Qaysi biri oldin yaratilgan va farq qancha?

Javob

Birinchi 8 belgi — soniyalar. 6add9a84 − 6add9a83 = 1, demak ikkinchisi taxminan 1 soniya keyin yaratilgan. Lekin "taxminan": vaqt soniya aniqligida, va ikki xil mashinaning soati bir xil bo'lmasligi mumkin.

5. Sxemasizlik: erkinlik va narxi

5.1 Kolleksiya hech narsani tekshirmaydi

Postgres'da matn ustuni text turida va NOT NULL — boshqa narsa kirmaydi (CREATE TABLE va cheklovlar). MongoDB kolleksiyasi esa sukut bo'yicha sxemasiz (schemaless): istalgan shakldagi hujjat kiradi.

Kanon buni sinadi — vazifalar kolleksiyasiga butunlay boshqa shakldagi hujjat yozdi, keyin matn maydonining BSON turi bo'yicha guruhladi:

js
await db.collection("vazifalar")
  .insertOne({ matn: 42, nimadir: ["boshqa", "shakl"] });
await db.collection("vazifalar").aggregate([
  { $group: { _id: { $type: "$matn" }, n: { $sum: 1 } } },
  { $sort: { _id: 1 } },
]).toArray();

Natija (kanon chiqishi):

text
turlar: [{"_id":"int","n":1},{"_id":"string","n":48}]

48 ta hujjatda matn — satr, bittasida — butun son. Hech qanday xato yo'q. $group va $type ni Aggregation pipeline darsida batafsil ko'ramiz; hozir faqat natijaga qarang.

5.2 Narxi qayerda chiqadi

Bu erkinlik yozishda qulay — migratsiya yo'q, yangi maydon qo'shish oson. Narxi o'qishda to'lanadi: ilova matn.toUpperCase() qilsa, 42 li hujjatda TypeError yiqiladi. Yoki aggregation $size ni massiv bo'lmagan maydonda chaqirib xato beradi — kanon buni haqiqatan tutdi (Aggregation pipeline darsida, xato matni bilan).

DB turlari xaritasi darsidagi gapni eslang: "sxema baribir bor — faqat u bazada emas, kodingizda". Mongo dunyosida sxemani ikki joyda qo'yish mumkin:

  1. Ilovada — Mongoose kutubxonasi bilan (Mongoose: schema va model). Eng keng tarqalgan yo'l.
  2. Bazada — kolleksiyaga $jsonSchema validator qo'shish. Bu MongoDB hujjatida bor (Schema Validation); kanon uni sinamadi, shuning uchun bu darsda faqat nomini aytamiz.

Tekshirib ko'ring: "Mongo sxemasiz, demak loyihalash kerak emas" — to'g'rimi?

Javob

Yo'q. Sxemasizlik — tekshiruv bazada yo'qligini bildiradi, sxema yo'qligini emas. Ilova baribir ma'lum shaklni kutadi. Shakl yozilmagan bo'lsa, u kodning har yeriga sochilib ketadi va xato o'qish paytida chiqadi. Shuning uchun Mongo loyihalarida ham sxema yoziladi — Mongoose'da yoki $jsonSchema da.

6. Vositalar: Docker, mongosh, Compass, Atlas

6.1 Docker'da MongoDB

Kanon MongoDB 8'ni Docker'da ko'tardi (Image, container va registry darsidagi buyruqlar). Kanon skriptidagi buyruq (qatorlar telefon uchun bo'lingan):

bash
docker run -d --name kanon27-mongo \
  -p 127.0.0.1:27018:27017 \
  -v kanon27-mongo-data:/data/db \
  mongo:8 --replSet rs0 --bind_ip_all
  • -p 127.0.0.1:27018:27017 — konteyner ichidagi 27017 (Mongo'ning sukut porti) kompyuterning 27018 portiga, faqat lokal manzilda.
  • -v …:/data/db — ma'lumot volume'da, konteyner o'chsa ham qoladi (Volume va bind mount).
  • --replSet rs0 — bitta tugunli replica set. Tranzaksiya va change streams uchun kerak; Replica set, tranzaksiyalar va change streams darsida ochamiz. Hozir uni "Mongo'ning to'liq rejimi" deb qabul qiling.

Replica set bir marta ishga tushiriladi (kanon skriptidan):

bash
docker exec kanon27-mongo mongosh --quiet --eval \
  'rs.initiate({_id:"rs0",
    members:[{_id:0, host:"127.0.0.1:27017"}]}).ok'

Image mongo:8 — kanonda server 8.3.13, mongosh 2.13.0, database-tools 100.19.1 edi. Konteynerda autentifikatsiya yo'q — faqat lokal sinov uchun. Prodakshn sozlamasi (foydalanuvchi, parol, rollar) — MongoDB xavfsizligi darsida.

6.2 Ulanish satri

Ilova bazaga ulanish satri orqali ulanadi. Kanon satri:

js
const satr = "mongodb://127.0.0.1:27018/vazifalar"
  + "?replicaSet=rs0&directConnection=true";
const u = new URL(satr);
console.log(u.protocol); // mongodb:
console.log(u.host); // 127.0.0.1:27018
console.log(u.pathname); // /vazifalar
console.log(u.searchParams.get("replicaSet")); // rs0

mongodb: — sxema, 127.0.0.1:27018 — server, /vazifalar — sukut baza, qolgani — sozlamalar. directConnection=true nega kerakligini keyingi darsda kanon xatosi bilan ko'ramiz: usiz drayver konteyner ichidagi manzilga ketib qoladi.

Bulut xizmatlari mongodb+srv:// sxemasini beradi: server ro'yxatini DNS'dan oladi. Bu hujjat bo'yicha; kanon sinamadi.

6.3 mongosh — terminal qobig'i

mongosh (MongoDB Shell) — Mongo'ning rasmiy terminal mijozi, psql'ning o'xshashi (psql chuqur). Ichida JavaScript ishlaydi: db — joriy baza, db.vazifalar — kolleksiya.

Kanon konteyner ichidagi mongosh'ni shunday chaqirdi:

bash
docker exec -it kanon27-mongo mongosh \
  "mongodb://127.0.0.1:27017/vazifalar?directConnection=true"

Interaktiv rejimda vazifalar> taklifi chiqadi. Kanon har buyruqni --eval bilan yubordi — chiqishlar shundan. Kolleksiyalar ro'yxati va hujjatlar soni:

js
db.getCollectionNames()
db.vazifalar.countDocuments()
text
[ 'vazifalar', 'foydalanuvchilar' ]
48

Bitta hujjat, faqat kerakli maydonlar bilan. Ikkinchi argument — projection: 1 — ko'rsat, 0 — yashir:

js
db.vazifalar.findOne(
  {pgId: 1},
  {_id: 0, matn: 1, teglar: 1, yaratilgan: 1}
)
text
{
  matn: "JavaScript kursining 26-qismini boshlash #o'qish",
  yaratilgan: ISODate('2026-10-01T03:30:00.000Z'),
  teglar: [ "o'qish" ]
}

mongosh sanani ISODate(…) deb ko'rsatadi — bu BSON Date. Maydon nomlari qo'shtirnoqsiz, satrlar bittalik qo'shtirnoqda (apostrofli satr — ikkitalikda). Node konsolidagi format bilan ma'nosi bir xil.

Massiv maydon bo'yicha qidirish. teglar massiv, lekin filtrda oddiy satr yozamiz:

js
db.vazifalar.find({teglar: "ish"}, {_id: 0, pgId: 1})
  .sort({pgId: 1}).limit(3).toArray()
text
[ { pgId: 6 }, { pgId: 12 }, { pgId: 20 } ]

{teglar: "ish"} — "teglar massivida ish elementi bor" degani. Mongo massivga tenglikni element bo'yicha tekshiradi. Postgres'da buning uchun 'ish' = ANY(teglar) yoki JOIN kerak edi (Massivlar, range, domain).

Bazaning hajmi:

js
db.stats().dataSize
text
13589

13 589 bayt — ikki kolleksiyadagi hujjatlar hajmi (siqilmagan). Diskdagi hajm boshqacha — WiredTiger saqlash dvigateli ma'lumotni siqadi. 500 000 vazifalik katta to'plamda bu farqni Aggregation pipeline darsida Postgres bilan solishtiramiz.

6.4 Compass va Atlas

  • MongoDB Compass — rasmiy grafik dastur: hujjatlarni ko'rish, so'rov yozish, indekslar va explain'ni chizib ko'rsatish. pgAdmin'ning o'xshashi. Kanonda GUI o'rnatilmadi — sinalmagan.
  • MongoDB Atlas — MongoDB kompaniyasining bulut xizmati (managed): server, zaxira, monitoring ularda. Bepul kichik klaster bor. Atlas Search va Vector Search uzoq vaqt faqat shu yerda edi. MongoDB 8.2 dan ular o'z serveringizda (Community Edition) ham sinov (preview) holatida bor — hujjatga ko'ra, 2026-10 holatiga (MongoDB xavfsizligi va operatsiyasi darsida tanishuv). Kanonda hisob ochilmadi — sinalmagan; tafsilot uchun mongodb.com/docs/atlas (2026-10-25 holatiga).

Maslahat: O'rganish uchun Docker yetadi: bepul, internet shart emas, xohlagan payt o'chirib qayta qurasiz. Atlas — real loyihada server boshqarishni xohlamasangiz.

7. Loyiha qadami: kanon tajribasi, loyihaga kirmaydi

Bu darsda vazifalar-api o'zgarmaydi. Kanon qilgan ish:

  1. kanon27-mongo konteynerini yuqoridagi buyruq bilan ko'tardi (bitta tugunli rs0).
  2. Postgres holat 11 namunasini (8 foydalanuvchi, 48 vazifa) Mongo'ga ko'chirdi: teglar va izohlar ichida, egasi — ishora.
  3. mongosh bilan kolleksiyalar, hujjat soni (48), projection, massiv qidiruvi va ObjectId vaqtini tekshirdi.
  4. Sxemasizlikni sinadi: matn: 42 jim kirdi.

Nega loyihaga kirmaydi? vazifalar ma'lumoti bog'langan (foydalanuvchi, vazifa, izoh, teg), hisobotlar va bir vaqtdagi yozuvlar bor — DB turlari xaritasi darsidagi tanlov hali ham to'g'ri. Mongo'ni taqqoslash uchun o'rganamiz: ish joyingizda Mongo'li loyiha chiqishi juda ehtimol.

8. Ko'p uchraydigan xatolar

Xato Oqibat To'g'risi
ObjectId vaqtini "yaratilgan sana" deb ishlatish Ko'chirish yoki importdan keyin sana yolg'on Sanani alohida maydonda saqlang
Sanani satr qilib yozish ("2026-10-01") Sana bo'yicha saralash va diapazon noto'g'ri ishlaydi new Date(…) — BSON Date
"Sxemasiz — tekshirmasa ham bo'ladi" Noto'g'ri turdagi hujjat o'qishda ilovani yiqitadi Mongoose yoki $jsonSchema
Kolleksiya nomida xato (db.vazifa) Xato yo'q — bo'sh natija; yozsangiz yangi kolleksiya ochiladi db.getCollectionNames() bilan tekshiring
Porti 0.0.0.0 ga ochilgan, parolsiz Mongo Internetdan hamma o'qiydi va o'chiradi 127.0.0.1 va auth (xavfsizlik darsi)

To'rtinchi qator Postgres'dan o'tgan o'quvchini ko'p chalg'itadi. Postgres relation "vazifa" does not exist deb baqiradi. Mongo esa jim: yo'q kolleksiyadan o'qish — bo'sh natija, yozish — yangi kolleksiya.

9. Mashqlar

Mashqlar kurs/mashqlar/27/42-mongodb-tuzilishi/ da. 2- va 3-mashq yechimlari Node 24 da tekshirilgan (biz ishga tushirdik, bazasiz).

1-mashq (oson): to'ldiring

  • Mongo'da jadvalning o'xshashi —
  • Hujjat diskda saqlanadigan ikkilik format —
  • ObjectId necha baytdan iborat?
  • ObjectId'ning birinchi necha bayti vaqt?
  • Bitta hujjatning maksimal hajmi (MB) —
Yechim
  • kolleksiya (collection) — hujjatlar guruhi, ustunlarni bilmaydi.
  • BSON — sana, ObjectId, int/double, Decimal128 turlarini biladi.
  • 12 bayt — ekranda 24 ta o'n oltilik belgi.
  • 4 bayt — Unix soniyalari; qolgani tasodifiy qiymat (5) va hisoblagich (3).
  • 16 MB — undan katta hujjatni yozib bo'lmaydi.

2-mashq (o'rta): ObjectId'dan vaqt

objectIdVaqti(hex) funksiyasini yozing: 24 belgili ObjectId satridan Date qaytarsin. Satr 24 ta o'n oltilik belgi bo'lmasa — TypeError tashlasin. Ikkita kanon id'si bilan sinang: 6add9a837ffcaf2b9d405510 (vazifa) va 6add9e3f1a1fac541a4002c0 (xavfsizlik darsida yaratilgan hujjat). Ular orasida necha soniya o'tgan?

Ishora: tekshiruv uchun /^[0-9a-f]{24}$/i (regex asoslari), vaqt uchun parseInt(…, 16).

Yechim
js
function objectIdVaqti(hex) {
  if (!/^[0-9a-f]{24}$/i.test(hex)) {
    throw new TypeError(`ObjectId emas: ${hex}`);
  }
  return new Date(parseInt(hex.slice(0, 8), 16) * 1000);
}

const a = objectIdVaqti("6add9a837ffcaf2b9d405510");
const b = objectIdVaqti("6add9e3f1a1fac541a4002c0");
console.log(a.toISOString());
console.log(b.toISOString());
console.log("farq:", (b - a) / 1000, "soniya");
try {
  objectIdVaqti("123");
} catch (x) {
  console.log(x.name, x.message);
}

Konsolda:

text
2026-10-25T05:58:27.000Z
2026-10-25T06:14:23.000Z
farq: 956 soniya
TypeError ObjectId emas: 123

956 soniya — 15 daqiqa 56 soniya: kanon ko'chirish skriptidan keyin xavfsizlik tajribasini ishga tushirgan oraliq. b - a — ikki Date ayirmasi millisekundlarda.

3-mashq (qiyin): qatorlardan hujjat

Postgres'dan uch xil qator keldi: vazifalar, izohlar, vazifa-teg bog'lanishlari. hujjatYasa(vazifalar, izohlar, teglar) funksiyasini yozing: har vazifaga teglar (satrlar massivi, alifbo tartibida) va izohlar ({ muallif, matn } massivi, id tartibida) qo'shilgan hujjatlar massivini qaytarsin. Izohsiz va tegsiz vazifada bo'sh massivlar bo'lsin. Postgres'dagi id ni pgId nomi bilan saqlang.

Ishora: Map bilan guruhlash — N+1 muammosi darsidagi batch usuli.

Yechim
js
const vazifalar = [
  { id: 1, matn: "Non olish #uy" },
  { id: 2, matn: "Hisobot #ish #tolov" },
  { id: 3, matn: "Kitob o'qish" },
];
const izohlar = [
  { id: 11, vazifa_id: 2, muallif: 1, matn: "Ertaga" },
  { id: 10, vazifa_id: 2, muallif: 2, matn: "Tez" },
  { id: 12, vazifa_id: 1, muallif: 1, matn: "Olindi" },
];
const teglar = [
  { vazifa_id: 2, nom: "tolov" },
  { vazifa_id: 2, nom: "ish" },
  { vazifa_id: 1, nom: "uy" },
];

function guruhla(qatorlar, kalit) {
  const m = new Map();
  for (const q of qatorlar) {
    if (!m.has(q[kalit])) m.set(q[kalit], []);
    m.get(q[kalit]).push(q);
  }
  return m;
}

function hujjatYasa(vazifalar, izohlar, teglar) {
  const iz = guruhla([...izohlar].sort((a, b) => a.id - b.id),
    "vazifa_id");
  const tg = guruhla(teglar, "vazifa_id");
  return vazifalar.map(({ id, ...qolgan }) => ({
    pgId: id,
    ...qolgan,
    teglar: (tg.get(id) ?? []).map((t) => t.nom).sort(),
    izohlar: (iz.get(id) ?? [])
      .map(({ muallif, matn }) => ({ muallif, matn })),
  }));
}

for (const h of hujjatYasa(vazifalar, izohlar, teglar)) {
  console.log(JSON.stringify(h));
}

Konsolda:

text
{"pgId":1,"matn":"Non olish #uy","teglar":["uy"],"izohlar":[{"muallif":1,"matn":"Olindi"}]}
{"pgId":2,"matn":"Hisobot #ish #tolov","teglar":["ish","tolov"],"izohlar":[{"muallif":2,"matn":"Tez"},{"muallif":1,"matn":"Ertaga"}]}
{"pgId":3,"matn":"Kitob o'qish","teglar":[],"izohlar":[]}

Kanon ko'chirishda xuddi shu ishni SQL tomonda qildi: array_agg(… ORDER BY t.nom) va json_agg(… ORDER BY i.id) (keyingi darsda kodi bilan). Bu yerda JavaScript'da — natija bir xil shakl. ?? [] — izohsiz vazifa uchun; usiz undefined.map xatosi chiqadi.

10. Real ishda

  • MongoDB — eng mashhur hujjat bazasi: kontent tizimlari, katalog, log va hodisalar, mobil ilovalar backend'i. Node ekotizimida (MERN — Mongo, Express, React, Node) uzoq yillar standart juftlik bo'lgan, eski va yangi loyihalarda tez-tez uchraydi.
  • Intervyu savollari: "ObjectId ichida nima bor?", "Mongo sxemasizmi?", "16 MB chegara nima uchun muhim?", "embed va reference farqi".
  • Kompaniyalar ko'pincha Atlas'dan foydalanadi — server boshqaruvi ularda. Lokal ishlash va testda esa Docker konteyneri.
  • Compass — qo'llab-quvvatlash va tahlil uchun qulay; dasturchilar kundalik ishda mongosh va drayverdan foydalanadi.

Xulosa

  • MongoDB: server → baza → kolleksiya → hujjat; kolleksiya va baza birinchi yozuvda o'zi yaratiladi.
  • Hujjat — ichma-ich obyekt va massivlar; diskda BSON (Date, ObjectId, int/double, Decimal128 bilan), maksimal 16 MB.
  • _id majburiy va noyob; sukut — ObjectId: 4 bayt vaqt + 5 tasodifiy + 3 hisoblagich. Uning vaqti — yozilgan payt, biznes sana emas.
  • Kolleksiya sukut bo'yicha sxemani tekshirmaydi — kanonda matn: 42 jim kirdi; tekshiruv Mongoose'da yoki $jsonSchema da.
  • Vositalar: Docker'da mongo:8, mongosh (psql o'xshashi), Compass (GUI), Atlas (bulut) — oxirgi ikkisi kanonda sinalmagan.

Keyingi dars: MongoDB native driver — rasmiy mongodb paketi bilan Node'dan ulanish, Postgres ma'lumotini ko'chirish, find, kursor va update operatorlari.

Manbalar

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
MongoDB nima: hujjat, kolleksiya, BSON va ObjectId — tuzilishi va vositalari — IlmHamroh