WisarWisar
Dasturlash kitobi/6-QISM — Database19 daqiqa

6.3-bob: MongoDB chuqur — aggregation pipeline, indekslar, relations

6-QISM — Ma'lumotlar bazasi (Database) · 3-mavzu


1. Kirish va motivatsiya

6.2-bobda MongoDB'ning asosiy CRUD'ini o'rgandik. Endi uning kuchli, professional imkoniyatlariga o'tamiz — bularsiz "MongoDB bilaman" deyish qiyin: aggregation pipeline (murakkab ma'lumot tahlili, guruhlash, hisoblash), indekslar (qidiruvni tezlashtirish — chuqur), va relations (embed vs reference — to'g'ri modellashtirish). Bu uchtasi — MongoDB'ni "o'yinchoq"dan "professional vosita"ga aylantiradi.

Oddiy find 6.2-bob yetmaydigan vaziyatlar ko'p: "har kategoriya bo'yicha o'rtacha narx", "eng ko'p sotilgan 10 mahsulot", "har oyning daromadi", "foydalanuvchilarni davlat bo'yicha guruhlab sanash". Bularni find qila olmaydi — aggregation pipeline kerak (SQL'dagi GROUP BY, agregat funksiyalarning MongoDB ekvivalenti). Bu — ma'lumotni bosqichma-bosqich qayta ishlash quvuri (pipeline — 5.4: stream ruhida).

Indeks — qidiruv tezligining kaliti (6.2: 2.15'da tegingan). Indekssiz MongoDB millionlab hujjatni birma-bir ko'rib chiqadi (sekin); indeks bilan — to'g'ridan topadi (tez). Va relations — eng muhim dizayn qarori: bog'liq ma'lumotni birga saqlash (embed) yoki alohida + ishora (reference)? Bu tanlov ilovaning tezligi va moslashuvchanligini belgilaydi.

O'xshatish (aggregation): pipeline — zavod konveyeri. Xom ma'lumot (hujjatlar) bir uchidan kiradi, har bosqich (stage) uni qayta ishlaydi: filtrlaydi ($match — yaroqsizni chiqaradi), guruhlaydi ($group — bo'lib hisoblaydi), tartiblaydi ($sort), shaklini o'zgartiradi ($project). Oxirida — tayyor natija. Har bosqich oldingisining chiqishini oladi (5.4: stream).

Nega muhim?

  • Murakkab tahlilfind qila olmaydigan hisobot/guruhlash (aggregation).
  • Tezlik — indekssiz katta DB sekin; indeks — production'da hayotiy.
  • To'g'ri dizayn — embed vs reference noto'g'ri tanlovi — qayta yozish.
  • Professional daraja — bu uchtasiz MongoDB yuzaki qoladi.

2. Nazariya — chuqur tushuntirish

2.1. Aggregation pipeline nima

Aggregation pipeline — ma'lumotni bosqichlar (stages) ketma-ketligi orqali qayta ishlash (mongodb docs). Har bosqich hujjatlarni o'zgartiradi va keyingisiga uzatadi:

text
  Collection  [$match]  [$group]  [$sort]  [$project]  Natija
              filtrla    guruhla   tartibla  shaklla

  Har bosqich OLDINGISINING chiqishini oladi (quvur — 5.4 ruhida)
js
db.orders.aggregate([
  { $match: { holat: "tugallandi" } },          // 1. faqat tugallangan
  { $group: { _id: "$userId", jami: { $sum: "$summa" } } },   // 2. user bo'yicha jami
  { $sort: { jami: -1 } },                       // 3. kamayish bo'yicha
  { $limit: 10 },                                // 4. top 10
]);

find vs aggregate: find 6.2-bob — oddiy filtrlash/o'qish. aggregatemurakkab qayta ishlash (guruhlash, hisoblash, birlashtirish). SQL'da: findSELECT ... WHERE; aggregateSELECT ... GROUP BY ... JOIN.

2.2. $match — filtrlash (eng oldinda)

$match — hujjatlarni filtrlaydi (find'dagi shart kabi — 6.2: 2.8):

js
{ $match: { holat: "faol", narx: { $gte: 1000 } } }

$matchni ENG OLDINGA qo'ying (mongodb docs): u hujjat sonini kamaytiradi — keyingi bosqichlar kamroq ma'lumot bilan ishlaydi (tez). Va boshida bo'lsa — indeksdan foydalanadi 2.9-bob. Bu — pipeline optimizatsiyasining asosiy qoidasi.

2.3. $group — guruhlash va hisoblash (eng muhim)

$group — hujjatlarni guruhlaydi va har guruh uchun hisoblaydi (SQL GROUP BY — mongodb docs):

js
{
  $group: {
    _id: "$kategoriya",                  // NIMA bo'yicha guruhlash (kategoriya)
    jami: { $sum: "$narx" },             // har guruhda narxlar yig'indisi
    ortacha: { $avg: "$narx" },          // o'rtacha
    soni: { $sum: 1 },                   // har guruhda nechta (har hujjatga +1)
    eng_qimmat: { $max: "$narx" },       // maksimal
  }
}

Agregat funksiyalar: $sum (yig'indi), $avg (o'rtacha), $min/$max, $count, $push (massivga yig'ish), $first/$last. _id — guruhlash kaliti (_id: null — hammasini bitta guruhga). $group "bloklovchi" (barcha ma'lumotni kutadi — katta ma'lumotda ehtiyot — 2.10).

2.4. $project — shaklni o'zgartirish

$project — chiqish hujjatining shaklini belgilaydi (qaysi maydon, hisoblangan maydon):

js
{
  $project: {
    ism: 1,                              // qoldir
    email: 1,
    _id: 0,                              // olib tashla
    toliqIsm: { $concat: ["$ism", " ", "$familiya"] },   // hisoblangan
    yilNarx: { $multiply: ["$narx", 12] },               // hisoblash
  }
}

$projectselect (6.2: 2.9) ning kuchli versiyasi: maydonlarni tanlash + yangi hisoblangan maydonlar. Pipeline'da kerakmas maydonlarni erta olib tashlash — tezlikni oshiradi.

2.5. $lookup — collection'larni birlashtirish (JOIN)

$lookup — boshqa collection'dan ma'lumot qo'shadi (SQL JOIN — 6.2: 2.13 populate'ga o'xshash, lekin pipeline ichida):

js
{
  $lookup: {
    from: "users",                       // qaysi collection'dan
    localField: "userId",                // bu collection'dagi maydon
    foreignField: "_id",                 // u collection'dagi maydon
    as: "user",                          // natija qaysi maydonga (massiv)
  }
}
// keyin $unwind bilan massivni yoyish: { $unwind: "$user" }

$lookup SEKIN bo'lishi mumkin (mongodb docs): u har hujjat uchun boshqa collection'da qidiradi. Ko'p ishlatish — performance muammosi. Yechim: ko'p birga-o'qiladigan ma'lumotni embed qiling 2.11-bob$lookup kerak bo'lmaydi. JOIN — SQL'ning kuchi; MongoDB'da uni minimallashtiring.

2.6. Boshqa muhim bosqichlar

text
  $sort    — tartiblash ({ narx: -1 })
  $limit   — N ta ({ $limit: 10 })
  $skip    — o'tkazib yuborish (sahifalash)
  $unwind  — massivni alohida hujjatlarga yoyish ([a,b]  2 hujjat)
  $count   — hujjatlar soni
  $addFields — yangi maydon qo'shish (boshqalarini saqlab)
  $facet   — bir vaqtda bir necha pipeline (ko'p hisobot birga)

2.7. Pipeline tartibi (optimizatsiya)

text
   To'g'ri tartib (tez):
  $match (filtrla — kam qoldiradi)  $sort  $group  $project
   erta filtrlash = keyingi bosqichlar kam ma'lumot bilan (2.2)

   Noto'g'ri:
  $group (hammasini guruhla)  $match (keyin filtrla)
   avval hammasini qayta ishladi, keyin tashladi (isrof)

Oltin qoida: $match va $sortboshida (indeksdan foydalanadi — 2.9, hujjat sonini kamaytiradi). $group, $unwind — keyin (ulardan keyin indeks ishlamaydi — mongodb docs).

2.8. Indeks nima va qanday ishlaydi (chuqur)

Indeks — ma'lum maydon(lar) bo'yicha saralangan ma'lumotnoma (kitobning alfavit indeksi kabi):

text
  Indekssiz qidiruv (collection scan):
  { email: "ali@a.uz" }  BUTUN collection'ni birma-bir ko'rish (million hujjat — sekin!)

  Indeks bilan (index scan):
  email indeksi  to'g'ridan "ali@a.uz" ni topish (B-tree — log vaqt — 3.6: tree)
   1,000,000 hujjatda ham bir necha qadam (juda tez)

Indeks — B-tree (3.6: balanslangan daraxt) tuzilmasi. Qidiruvni O(n) (hammasini ko'rish) dan O(log n) (daraxt bo'yicha) ga keltiradi (3.1: Big-O). Bu — katta DB'da hayot-mamot farqi (sekunddan millisekundga).

2.9. Indeks turlari

js
// Yagona indeks (bitta maydon)
userSchema.index({ email: 1 });          // 1: o'sish; -1: kamayish

// Birikma (compound) indeks (bir necha maydon)
orderSchema.index({ userId: 1, createdAt: -1 });   // userId + sana bo'yicha

// Noyob (unique) indeks
userSchema.index({ email: 1 }, { unique: true });   // takror email rad

// Matn (text) indeks — qidiruv uchun
productSchema.index({ nom: "text", tavsif: "text" });   // $text qidiruv

// TTL indeks — vaqt o'tgach o'chirish (5.18: OTP, sessiya)
otpSchema.index({ createdAt: 1 }, { expireAfterSeconds: 120 });

Birikma indeks tartibi — ESR qoidasi (mongodb): Equality (aniq moslik) Sort (tartiblash) Range (oraliq). Masalan { userId: 1 (equality), createdAt: -1 (sort) }. Tartib muhim — noto'g'ri tartib indeksni befoyda qiladi.

2.10. Indeks narxi (har doim emas)

Indeks tekin emas — afzallik va narx balansi:

text
   Indeks foydasi: qidiruv tez (o'qish — 2.8)
   Indeks narxi:
  - Yozish sekinroq (har insert/update'da indeks ham yangilanadi)
  - Joy oladi (disk/RAM)
  - Ko'p indeks — sekinlik, isrof

   Tez-tez QIDIRILADIGAN maydonga indeks (email, userId, sana)
   Kam ishlatiladiganga — kerak emas

explain() bilan tekshiring: db.users.find({...}).explain("executionStats") — so'rov indeksdan foydalandimi (IXSCAN) yoki butun collection'ni ko'rdimi (COLLSCAN — yomon). Bu — 6.13 (query optimization) da chuqur.

2.11. Relations: Embed (birga saqlash)

MongoDB'da bog'liq ma'lumotni saqlashning birinchi yo'li — embed (ichiga joylash — 6.1: 2.10 denormalizatsiya):

js
// Foydalanuvchi va manzili — BIRGA (embed)
{
  _id: 1, ism: "Ali",
  manzil: { shahar: "Toshkent", kocha: "Amir Temur" },   // ichma-ich
  telefonlar: [{ raqam: "+998901112233", tur: "ish" }],   // massiv
}

Embed afzalligi: bitta o'qishda hammasi keladi (JOIN/lookup yo'q — tez); atomik yangilash (bitta hujjat). Kamchiligi: hujjat kattalashadi; takror (agar boshqa joyda ham kerak bo'lsa). MongoDB hujjat chegarasi — 16MB (juda katta massivni embed qilmang).

2.12. Relations: Reference (ishora)

Ikkinchi yo'l — reference (boshqa collection'ga ishora — 6.1: 2.5 FK, 6.2: 2.13):

js
// Buyurtma — user'ga ishora (reference)
{ _id: 10, userId: ObjectId("1"), summa: 50000 }   // userId — User'ga ishora
// User alohida collection'da; populate/lookup bilan birlashtiriladi (6.2: 2.13)

Reference afzalligi: ma'lumot takrorlanmaydi (user bir joyda); mustaqil o'sadi (cheksiz buyurtma); ko'p joyda ulashiladi. Kamchiligi: birlashtirishga qo'shimcha so'rov (populate/$lookup — sekinroq).

2.13. Embed vs Reference — qachon qaysi biri (eng muhim qaror)

text
  EMBED qiling (birga saqlang) — agar:
   Bog'liq ma'lumot HAR DOIM birga o'qiladi (manzil, profil tafsiloti)
   Soni KICHIK va CHEGARALANGAN (bir necha telefon, bir necha rasm)
   Mustaqil o'zgarmaydi (parent bilan birga)
   Atomik yangilash kerak

  REFERENCE qiling (ishora) — agar:
   Ma'lumot MUSTAQIL so'raladi (user — alohida ham kerak)
   CHEKSIZ o'sadi (foydalanuvchining buyurtmalari — minglab)
   Ko'p parent'da ULASHILADI (mahsulot — ko'p buyurtmada)
   Tez-tez o'zgaradi (takror joyda yangilash muammosi)

Misol (oneuptime/mongodb): foydalanuvchi manzili embed (birga, kichik). Foydalanuvchi buyurtmalari reference (cheksiz, mustaqil). Blog post + kommentlar kommentlar kam bo'lsa embed, ko'p bo'lsa reference. Qoida: "birga o'qiladimi + kichikmi?" embed; "mustaqilmi + ko'paymi?" reference.

2.14. One-to-Few, One-to-Many, Many-to-Many

text
  One-to-Few (1:bir necha) — embed (user  bir necha manzil)
  One-to-Many (1:ko'p)     — reference (user  minglab buyurtma)
  Many-to-Many (ko'p:ko'p) — reference (talaba  kurslar; ikki tomon ID massivi)

Many-to-Many misoli: talaba bir necha kursga, kurs bir necha talabaga. MongoDB'da — har ikkisida ID massivi (student.kurslar: [id], course.talabalar: [id]), yoki oraliq collection (SQL'dagi junction table — 6.7). SQL bu yerda tabiiyroq (JOIN).

2.15. Mongoose'da aggregation va indeks

js
// Aggregation (Mongoose model orqali — 6.2: 2.6)
const natija = await Order.aggregate([
  { $match: { holat: "tugallandi" } },
  { $group: { _id: "$userId", jami: { $sum: "$summa" } } },
]);

// Indeks (schema'da — 6.2: 2.15)
orderSchema.index({ userId: 1, createdAt: -1 });   // birikma (2.9)
// Mongoose ilova boshida indekslarni avtomatik yaratadi (autoIndex)

Production'da autoIndex: false: Mongoose har ishga tushganda indeks yaratishga urinadi (dev'da qulay, production'da sekin). Production'da indekslarni alohida (deploy paytida) yarating (autoIndex: false).

2.16. Aggregation use-case'lar (real)

text
  E-commerce:  har kategoriya daromadi; top mahsulotlar; oylik savdo
  Ijtimoiy:    har post like/komment soni; faol foydalanuvchilar
  Analitika:   kunlik/oylik statistika; o'rtacha qiymatlar
  Hisobot:     guruhlangan, hisoblangan ma'lumot (dashboard — 11)

2.17. Xavfsizlik va best practices (14)

text
   $match'ni oldinga (indeks + kam ma'lumot — 2.2, 2.7)
   $lookup'ni minimallashtiring (embed afzal — 2.5)
   Tez-qidiriladigan maydonga indeks 2.10-bob; explain() bilan tekshiring
   Hujjat 16MB chegarasi (katta massivni embed qilmang — 2.11)
   Aggregation'da foydalanuvchi kiritgan ma'lumotni validatsiya (injection — 14)
   Katta $group — xotira (allowDiskUse kerak bo'lishi mumkin — 2.3)
   Production'da autoIndex: false (2.15)

2.18. Tranzaksiyalar (bir necha hujjatni atomik o'zgartirish)

Bitta hujjatni yangilash MongoDB'da doim atomik (embed'ning kuchi — 2.11). Ammo bir necha hujjat (yoki bir necha collection) birgalikda o'zgarishi kerak bo'lsa — masalan pul o'tkazmasida bir hisobdan yechib, ikkinchisiga qo'shish — tranzaksiya kerak. Tranzaksiya: yo hammasi bajariladi, yo hech biri (SQL'dagi ACID atomiklik — 6.1).

js
const session = await mongoose.startSession();
try {
  await session.withTransaction(async () => {
    await Account.updateOne({ _id: a }, { $inc: { balans: -100 } }, { session });
    await Account.updateOne({ _id: b }, { $inc: { balans: +100 } }, { session });
  });   // ikkisi ham muvaffaqiyatli  commit; biri xato  hammasi bekor (rollback)
} finally {
  session.endSession();
}

Tranzaksiya faqat replica set'da: MongoDB tranzaksiyalari replica set (yoki sharded cluster) talab qiladi — yakka (standalone) serverda ishlamaydi. Development'da bitta tugunli replica set yetadi. Narxi bor (bloklash, sekinroq) — shuning uchun tranzaksiyadan faqat haqiqatan bir necha hujjat atomik bo'lishi shart bo'lganda foydalaning. Ko'p holatda to'g'ri embed (bog'liq ma'lumot bitta hujjatda — 2.11) tranzaksiya zaruriyatini yo'q qiladi.


3. Sintaksis — tez ma'lumotnoma

js
// Aggregation (2.1)
await Model.aggregate([
  { $match: { ... } },                  // filtrla (oldinda — 2.2)
  { $group: { _id: "$field", jami: { $sum: "$x" }, soni: { $sum: 1 } } },   // guruhla (2.3)
  { $sort: { jami: -1 } },              // tartibla
  { $project: { _id: 0, ism: 1 } },     // shaklla (2.4)
  { $lookup: { from, localField, foreignField, as } },   // JOIN (2.5)
]);

// Indeks (2.9)
schema.index({ email: 1 }, { unique: true });
schema.index({ userId: 1, createdAt: -1 });   // birikma (ESR — 2.9)

// Embed vs reference 2.13-bob: birga+kichik  embed; mustaqil+ko'p  reference

4. Batafsil kod namunalari

Misol 1 — Oddiy aggregation (kategoriya bo'yicha — 2.1, 2.3)

js
// Har kategoriya bo'yicha mahsulot soni va o'rtacha narx
const statistika = await Product.aggregate([
  { $match: { faol: true } },                    // 1. faqat faol (oldinda — 2.2)
  {
    $group: {
      _id: "$kategoriya",                          // kategoriya bo'yicha guruhla (2.3)
      soni: { $sum: 1 },                           // har guruhda nechta
      ortachaNarx: { $avg: "$narx" },              // o'rtacha narx
      engQimmat: { $max: "$narx" },                // eng qimmat
    },
  },
  { $sort: { soni: -1 } },                         // ko'pdan kamga (2.6)
]);
// Natija: [{ _id: "telefon", soni: 45, ortachaNarx: 3500000, ... }, ...]

Misol 2 — Top 10 mijoz (sotuv bo'yicha — 2.3, 2.5)

js
// Eng ko'p xarid qilgan 10 mijoz (user ma'lumoti bilan)
const topMijozlar = await Order.aggregate([
  { $match: { holat: "tugallandi" } },             // tugallangan buyurtmalar
  {
    $group: {
      _id: "$userId",                               // mijoz bo'yicha
      jamiXarid: { $sum: "$summa" },                // jami summa
      buyurtmaSoni: { $sum: 1 },
    },
  },
  { $sort: { jamiXarid: -1 } },                     // kamayish
  { $limit: 10 },                                   // top 10 (2.6)
  {
    $lookup: {                                      // user ma'lumotini qo'sh (2.5)
      from: "users", localField: "_id", foreignField: "_id", as: "user",
    },
  },
  { $unwind: "$user" },                             // massivni yoy (2.6)
  { $project: { _id: 0, ism: "$user.ism", jamiXarid: 1, buyurtmaSoni: 1 } },   // shaklla (2.4)
]);

Misol 3 — Oylik daromad hisoboti (sana guruhlash — 2.3)

js
// Har oyning daromadi (dashboard uchun — 2.16)
const oylikDaromad = await Order.aggregate([
  { $match: { holat: "tugallandi", createdAt: { $gte: new Date("2026-01-01") } } },
  {
    $group: {
      _id: { yil: { $year: "$createdAt" }, oy: { $month: "$createdAt" } },   // yil+oy bo'yicha
      daromad: { $sum: "$summa" },
      buyurtmalar: { $sum: 1 },
    },
  },
  { $sort: { "_id.yil": 1, "_id.oy": 1 } },         // xronologik
]);
// Natija: [{ _id: { yil: 2026, oy: 1 }, daromad: 15000000, buyurtmalar: 320 }, ...]

Misol 4 — $facet (bir vaqtda ko'p hisobot — 2.6)

js
// Bitta so'rovda bir necha statistika (dashboard — 2.16)
const dashboard = await Order.aggregate([
  {
    $facet: {
      jami: [{ $group: { _id: null, summa: { $sum: "$summa" }, soni: { $sum: 1 } } }],
      holatBoyicha: [{ $group: { _id: "$holat", soni: { $sum: 1 } } }],
      songgi5: [{ $sort: { createdAt: -1 } }, { $limit: 5 }],
    },
  },
]);
// dashboard[0].jami, .holatBoyicha, .songgi5 — hammasi bir so'rovda

Misol 5 — Indekslar (schema'da — 2.9)

js
const productSchema = new mongoose.Schema({
  nom: String, narx: Number, kategoriya: String, userId: mongoose.Schema.Types.ObjectId,
}, { timestamps: true });

// Yagona indeks (tez-qidiriladigan — 2.9)
productSchema.index({ kategoriya: 1 });

// Birikma indeks (ESR qoidasi: equality  sort — 2.9)
productSchema.index({ kategoriya: 1, narx: -1 });   // kategoriya bo'yicha, narx tartibida

// Matn indeks (qidiruv — 2.9)
productSchema.index({ nom: "text", tavsif: "text" });

// Production'da avtomatik indeks o'chirilgan (2.15)
mongoose.set("autoIndex", process.env.NODE_ENV !== "production");

export const Product = mongoose.model("Product", productSchema);

// Matn qidiruv (text indeks bilan)
await Product.find({ $text: { $search: "telefon" } });

Misol 6 — Embed modellashtirish (one-to-few — 2.11, 2.13)

js
// Foydalanuvchi + manzillari (embed — kichik, birga o'qiladi — 2.13)
const userSchema = new mongoose.Schema({
  ism: String,
  email: String,
  manzillar: [{                                    // embed massiv (one-to-few — 2.14)
    shahar: String,
    kocha: String,
    asosiy: { type: Boolean, default: false },
  }],
});
// Bitta o'qishda user + barcha manzillar (JOIN yo'q — tez — 2.11)
const user = await User.findById(id);
console.log(user.manzillar);   // darrov bor (qo'shimcha so'rovsiz)

Misol 7 — Reference modellashtirish (one-to-many — 2.12, 2.13)

js
// Buyurtma — user'ga reference (cheksiz o'sadi — 2.13, 2.14)
const orderSchema = new mongoose.Schema({
  user: { type: mongoose.Schema.Types.ObjectId, ref: "User", required: true, index: true },   // indeks!
  mahsulotlar: [{
    mahsulot: { type: mongoose.Schema.Types.ObjectId, ref: "Product" },
    miqdor: Number,
    narx: Number,                                  // narxni NUSXALANG (mahsulot narxi keyin o'zgarsa ham — snapshot)
  }],
  summa: Number,
}, { timestamps: true });

// populate bilan birlashtirish (6.2: 2.13)
const order = await Order.findById(id).populate("user", "ism email");

Muhim nuans: buyurtmadagi narx — mahsulotga reference qilinsa ham, nusxalanadi (snapshot). Sababi: mahsulot narxi keyin o'zgarsa, eski buyurtma o'sha vaqtdagi narxni saqlashi kerak (tarix). Bu — embed/reference aralashmasi (amaliy hikmat).

Misol 8 — Many-to-Many (2.14)

js
// Talaba  Kurs (many-to-many — 2.14)
const studentSchema = new mongoose.Schema({
  ism: String,
  kurslar: [{ type: mongoose.Schema.Types.ObjectId, ref: "Course" }],   // ID massivi
});
const courseSchema = new mongoose.Schema({
  nom: String,
  talabalar: [{ type: mongoose.Schema.Types.ObjectId, ref: "Student" }],
});
// Talaba kurslari: Student.findById(id).populate("kurslar")
//  Ikki tomonni sinxron saqlash kerak (talabaga kurs qo'shsangiz, kursga talaba ham)
//    Murakkab bog'lanish — ba'zan SQL (JOIN) tabiiyroq (6.7)

5. To'g'ri va noto'g'ri holatlar

1) $match'ni oxirga qo'yish

js
//  avval hammasini guruhla, keyin filtrla (isrof — 2.7)
[{ $group: {...} }, { $match: {...} }]

//  avval filtrla (kam ma'lumot — 2.2)
[{ $match: {...} }, { $group: {...} }]

2) Tez-qidiriladigan maydonga indekssiz

text
 email/userId indekssiz  million hujjatda sekin (COLLSCAN — 2.8)
 index({ email: 1 }) (IXSCAN — tez)

3) Cheksiz o'sadigan ma'lumotni embed qilish

js
//  foydalanuvchining barcha buyurtmalari embed (16MB chegara — 2.11)
{ ism: "Ali", buyurtmalar: [/* minglab */] }

//  reference (mustaqil collection — 2.12, 2.13)

4) $lookup'ni ortiqcha ishlatish

text
 har so'rovda ko'p $lookup (sekin — 2.5)
 ko'p-o'qiladigan ma'lumotni embed (lookup'siz — 2.13)

5) Ko'p kerakmas indeks

text
 har maydonga indeks (yozish sekin, joy — 2.10)
 faqat tez-qidiriladigan maydon (explain() bilan tekshiring)

6. Keng tarqalgan xatolar va yechimlari

Xato 1 — Aggregation sekin

Sababi: $match oldinda emas; indeks yo'q 2.7-bob. Yechimi: $match/$sort boshida; tegishli indeks; explain() bilan tahlil qiling.

Xato 2 — $group xotira xatosi (katta ma'lumot)

Sababi: $group bloklovchi, ko'p ma'lumotni xotiraga oladi 2.3-bob. Yechimi: $match bilan kamaytiring; { allowDiskUse: true }.

Xato 3 — Indeks yaratilmaydi (production sekin)

Sababi: autoIndex production'da 2.15-bob. Yechimi: autoIndex: false; indekslarni alohida yarating.

Xato 4 — Embed qilingan hujjat 16MB'dan oshdi

Sababi: cheksiz massivni embed 2.11-bob. Yechimi: reference'ga o'tkazing 2.13-bob.

Xato 5 — $lookup natijasi massiv (kutilmagan)

Sababi: $lookup doim massiv qaytaradi 2.5-bob. Yechimi: $unwind bilan yoying (bitta bo'lsa).

Xato 6 — Embed ma'lumot eskirdi (takror)

Sababi: embed qilingan ma'lumot manbada o'zgardi, nusxasi eski 2.13-bob. Yechimi: o'zgaruvchan ma'lumot — reference; yoki yangilashda barcha nusxani.


7. Integratsiya — bu mavzu stack'ning qayerida uchraydi

  • MongoDB/Mongoose 6.2-bob: asosiy CRUD; bu — chuqurlashtirish.
  • DB asoslari 6.1-bob: normalizatsiya/denormalizatsiya, relations.
  • Tree 3.6-bob: indeks — B-tree; Big-O 3.1-bob.
  • Stream 5.4-bob: pipeline g'oyasi.
  • Query optimization 6.13-bob: explain, indeks tahlili.
  • SQL JOIN 6.7-bob: $lookup ekvivalenti.
  • Dashboard (11): aggregation hisobotlari.
  • Performance 5.21-bob: indeks + kesh birga.
  • NestJS 8.13-bob: Mongoose aggregation.

8. Eng yaxshi amaliyotlar (best practices)

  • $match/$sort pipeline boshida (indeks + kam ma'lumot — 2.2, 2.7).
  • $lookup minimallashtiring (embed afzal — 2.5, 2.13).
  • Tez-qidiriladigan maydonga indeks (email, ref, sana — 2.9, 2.10).
  • Birikma indeks ESR tartibida (equality sort range — 2.9).
  • explain() bilan tekshiring (COLLSCAN yomon, IXSCAN yaxshi — 2.10).
  • Embed: birga+kichik+chegaralangan; reference: mustaqil+ko'p 2.13-bob.
  • Hujjat 16MB chegarasi (cheksiz embed qilma — 2.11).
  • O'zgaruvchan/takror ma'lumotda snapshot yoki reference (2.13, Misol 7).
  • Production'da autoIndex: false 2.15-bob.
  • Katta $group — allowDiskUse 2.3-bob; foydalanuvchi ma'lumotini validatsiya (14).

9. Amaliy loyiha: "Analitika va Optimizatsiya (MongoDB)"

MongoDB'ning kuchli imkoniyatlarini mustahkamlash.

Maqsad

Aggregation pipeline, indekslar va to'g'ri relations modellashtirish bilan tahliliy, tez ishlaydigan ma'lumot qatlamini qurish (e-commerce yoki ijtimoiy tarmoq).

Talablar (requirements)

  1. Modellar: User, Product, Order — embed va reference to'g'ri tanlangan (Misol 6, 7, 2.13).
  2. Aggregation hisobotlar: kategoriya bo'yicha statistika; top mijozlar; oylik daromad (Misol 1-3, 2.3).
  3. $lookup: buyurtma + user/mahsulot birlashtirish (Misol 2, 2.5).
  4. $facet: dashboard uchun bir necha hisobot bir so'rovda (Misol 4, 2.6).
  5. Indekslar: tez-qidiriladigan maydonlarga; birikma (ESR); matn qidiruv (Misol 5, 2.9).
  6. Pipeline optimizatsiya: $match oldinda; explain() bilan tekshiring (2.7, 2.10).
  7. Many-to-many: misol (talaba-kurs yoki teg-mahsulot — Misol 8, 2.14).
  8. Snapshot: buyurtmada narxni nusxalash (Misol 7, 2.13).
  9. Production: autoIndex: false 2.15-bob.

Maslahatlar (hint)

  • $match birinchi (indeks + kam ma'lumot — 2.7).
  • $group: { _id: "$field", jami: { $sum: "$x" }, soni: { $sum: 1 } } 2.3-bob.
  • Embed: kichik+birga; reference: ko'p+mustaqil 2.13-bob.
  • Birikma indeks ESR (equalitysort — 2.9).
  • $lookup natijasi massiv $unwind (5-xato).
  • explain("executionStats") — IXSCAN bo'lsin 2.10-bob.

"Tayyor" mezonlari (acceptance criteria)

  • Modellar embed/reference to'g'ri tanlangan (asoslangan).
  • Aggregation hisobotlar ishlaydi (guruhlash, hisoblash).
  • $lookup bilan birlashtirish.
  • $facet bilan dashboard.
  • Indekslar (yagona, birikma, matn).
  • $match oldinda; explain IXSCAN ko'rsatadi.
  • Many-to-many misoli.
  • Snapshot (buyurtma narxi).

Yechim kodi ataylab berilmagan — bu loyihani o'zingiz yozib ko'ring.


10. Xulosa va keyingi bobga ko'prik

Bu bobda MongoDB'ning professional imkoniyatlarini chuqur o'rgandik:

  • Aggregation pipeline (bosqichlar quvuri — 2.1): $match (filtr, oldinda — 2.2), $group (guruhlash/hisoblash — 2.3), $project (shakl — 2.4), $lookup (JOIN — 2.5); tartib optimizatsiyasi 2.7-bob.
  • Indekslar (B-tree, qidiruv tezligi — 2.8); turlari (yagona/birikma/unique/text/TTL — 2.9); ESR qoidasi; narxi (yozish/joy — 2.10); explain().
  • Relations: embed (birga, kichik — 2.11) vs reference (mustaqil, ko'p — 2.12); qachon qaysi biri 2.13-bob; one-to-few/many, many-to-many 2.14-bob.
  • Tranzaksiyalar (bir necha hujjatni atomik — replica set — 2.18).
  • Use-case'lar (hisobot/dashboard — 2.16); xavfsizlik/performance 2.17-bob.

Keyingi bob — 6.4-bob: SQL asoslari — CREATE, INSERT, SELECT, UPDATE, DELETE, WHERE. MongoDB (NoSQL) dunyosini chuqur ko'rdik; endi ikkinchi katta dunyoga — relatsion DB va SQL tiliga — o'tamiz. Jadval yaratish, ma'lumot qo'shish/o'qish/yangilash/o'chirish, shartlar (WHERE), turlar va cheklovlar (constraints) — SQL'ning poydevori. Bu — PostgreSQL/MySQL va ORM'lar uchun asos.


Foydalanilgan rasmiy/ishonchli manbalar

  • mongodb.com/docs — Aggregation Pipeline ($match, $group, $lookup, $project), optimization
  • mongodb.com/docs/data-modeling — Embedding vs References best practices; ESR indeks qoidasi
  • mongodb.com — Performance Best Practices: Indexing

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
6.3-bob: MongoDB chuqur — aggregation pipeline, indekslar, relations — Wisar