12-bo‘lim

Agregatsiya quvuri - asoslar

Quvur g'oyasi, $match va $group, $sum va $avg, $sort va $limit, $project hamda bosqichlar tartibining ahamiyati.

🕑 12 daqiqa o‘qish 📄 665 so‘z 👁 0 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. Quvur g'oyasi
  2. $match va $group
  3. Agregat operatorlar
  4. Ikkita maydon bo'yicha guruhlash
  5. $project bilan ko'rinishni tozalash
  6. Bosqichlar tartibi
  7. $count va $limit
  8. find va aggregate
  9. Xulosa

find savolga "qaysi hujjatlar?" deb javob beradi. Agregatsiya esa "qancha, o'rtacha qancha, qaysi guruhda eng ko'p" degan savollarga javob beradi.

JavaScript
db.sotuv.insertMany([
  { _id: 1, filial: "Namangan", janr: "roman",   soni: 3, narx: 85000,
    sana: ISODate("2026-01-12T00:00:00Z") },
  { _id: 2, filial: "Namangan", janr: "ilmiy",   soni: 1, narx: 120000,
    sana: ISODate("2026-01-28T00:00:00Z") },
  { _id: 3, filial: "Toshkent", janr: "roman",   soni: 5, narx: 95000,
    sana: ISODate("2026-02-03T00:00:00Z") },
  { _id: 4, filial: "Toshkent", janr: "bolalar", soni: 8, narx: 47000,
    sana: ISODate("2026-02-14T00:00:00Z") },
  { _id: 5, filial: "Namangan", janr: "roman",   soni: 2, narx: 64000,
    sana: ISODate("2026-02-22T00:00:00Z") },
  { _id: 6, filial: "Samarqand", janr: "ilmiy",  soni: 4, narx: 110000,
    sana: ISODate("2026-03-05T00:00:00Z") },
  { _id: 7, filial: "Toshkent", janr: "roman",   soni: 1, narx: 72000,
    sana: ISODate("2026-03-11T00:00:00Z") },
  { _id: 8, filial: "Namangan", janr: "bolalar", soni: 6, narx: 51000,
    sana: ISODate("2026-03-19T00:00:00Z") }
])

Quvur g'oyasi #

Agregatsiya - bosqichlar ro'yxati. Har bosqich hujjatlarni oladi, o'zgartiradi va keyingisiga uzatadi.

Har bosqich oldingisining natijasini oladi To'plam 8 hujjat $match 5 hujjat qoldi $group 3 guruh $sort tartiblandi natija Bosqichlar tartibi tezlikni belgilaydi $match ni boshiga qo'ying - keyingi bosqichlar kamroq hujjat bilan ishlaydi Boshdagi $match indeksdan foydalana oladi, o'rtadagisi esa yo'q $project va $sort ni keraksiz erta chaqirmang - ular ish qo'shadi
Quvur - konveyer: har bosqich oldingisidan kelgan hujjatlar ustida ishlaydi

$match va $group #

Eng ko'p ishlatiladigan juftlik:

JavaScript
db.sotuv.aggregate([
  { $group: { _id: "$filial", jami_soni: { $sum: "$soni" } } },
  { $sort: { jami_soni: -1 } }
])
Natija
[
  { _id: 'Toshkent', jami_soni: 14 },
  { _id: 'Namangan', jami_soni: 12 },
  { _id: 'Samarqand', jami_soni: 4 }
]

$group dagi _id - guruhlash kaliti. U majburiy.

YozuvMa'nosi
_id: "$filial"Filial bo'yicha guruhla
_id: nullHammasini bitta guruhga
_id: { f: "$filial", j: "$janr" }Ikkita maydon bo'yicha
JavaScript
db.sotuv.aggregate([
  { $match: { janr: "roman" } },
  { $group: {
      _id: "$filial",
      soni: { $sum: "$soni" },
      tushum: { $sum: { $multiply: ["$soni", "$narx"] } },
      ortacha_narx: { $avg: "$narx" }
  } },
  { $sort: { tushum: -1 } }
])
Natija
[
  { _id: 'Toshkent', soni: 6, tushum: 547000, ortacha_narx: 83500 },
  { _id: 'Namangan', soni: 5, tushum: 383000, ortacha_narx: 74500 }
]

Agregat operatorlar #

OperatorNima qiladi
$sumYig'indi ($sum: 1 - hujjatlarni sanaydi)
$avgO'rtacha
$min / $maxEng kichik / eng katta
$first / $lastGuruhdagi birinchi / oxirgi qiymat
$pushHamma qiymatni massivga yig'adi
$addToSetTakrorlanmagan qiymatlarni massivga
$countHujjatlar soni (alohida bosqich sifatida ham)
JavaScript
db.sotuv.aggregate([
  { $group: {
      _id: "$janr",
      hujjatlar: { $sum: 1 },
      eng_qimmat: { $max: "$narx" },
      eng_arzon: { $min: "$narx" },
      filiallar: { $addToSet: "$filial" }
  } },
  { $sort: { _id: 1 } }
])
Natija
[
  {
    _id: 'bolalar',
    hujjatlar: 2,
    eng_qimmat: 51000,
    eng_arzon: 47000,
    filiallar: [ 'Toshkent', 'Namangan' ]
  },
  {
    _id: 'ilmiy',
    hujjatlar: 2,
    eng_qimmat: 120000,
    eng_arzon: 110000,
    filiallar: [ 'Samarqand', 'Namangan' ]
  },
  {
    _id: 'roman',
    hujjatlar: 4,
    eng_qimmat: 95000,
    eng_arzon: 64000,
    filiallar: [ 'Namangan', 'Toshkent' ]
  }
]
$sum: 1 va $sum: "$maydon" farqi

Ikkalasi bir xil operator, lekin butunlay boshqa narsani hisoblaydi:

YozuvNimani hisoblaydi
{ $sum: 1 }Guruhdagi hujjatlar soni
{ $sum: "$soni" }soni maydonlarining yig'indisi

Yuqoridagi misolda roman janrida 4 ta hujjat bor, lekin sotilgan nusxalar soni 11 ta. Bu ikki xil savol va ikki xil javob.

Xato shu yerda tug'iladi: "nechta sotildi?" degan savolga $sum: 1 yozib qo'yish. Natijada hisobot yozuvlar sonini ko'rsatadi, sotilgan mahsulot sonini emas.

$sum: 1 da 1 - har hujjat uchun qo'shiladigan qiymat. Shuning uchun u hujjatlarni sanaydi.

Ikkita maydon bo'yicha guruhlash #

JavaScript
db.sotuv.aggregate([
  { $group: {
      _id: { filial: "$filial", janr: "$janr" },
      soni: { $sum: "$soni" }
  } },
  { $sort: { "_id.filial": 1, "_id.janr": 1 } }
])
Natija
[
  { _id: { filial: 'Namangan', janr: 'bolalar' }, soni: 6 },
  { _id: { filial: 'Namangan', janr: 'ilmiy' }, soni: 1 },
  { _id: { filial: 'Namangan', janr: 'roman' }, soni: 5 },
  { _id: { filial: 'Samarqand', janr: 'ilmiy' }, soni: 4 },
  { _id: { filial: 'Toshkent', janr: 'bolalar' }, soni: 8 },
  { _id: { filial: 'Toshkent', janr: 'roman' }, soni: 6 }
]

Natijadagi _id endi hujjat - shuning uchun saralashda "_id.filial" yozuvi ishlatildi.

$project bilan ko'rinishni tozalash #

JavaScript
db.sotuv.aggregate([
  { $group: {
      _id: { filial: "$filial", janr: "$janr" },
      soni: { $sum: "$soni" }
  } },
  { $project: {
      _id: 0,
      filial: "$_id.filial",
      janr: "$_id.janr",
      soni: 1
  } },
  { $sort: { filial: 1, janr: 1 } }
])
Natija
[
  { soni: 6, filial: 'Namangan', janr: 'bolalar' },
  { soni: 1, filial: 'Namangan', janr: 'ilmiy' },
  { soni: 5, filial: 'Namangan', janr: 'roman' },
  { soni: 4, filial: 'Samarqand', janr: 'ilmiy' },
  { soni: 8, filial: 'Toshkent', janr: 'bolalar' },
  { soni: 6, filial: 'Toshkent', janr: 'roman' }
]

Endi natija tekis va o'qishga qulay.

Bosqichlar tartibi #

Bir xil natija, ikki xil tezlik:

JavaScript
db.sotuv.aggregate([
  { $match: { filial: "Namangan" } },
  { $group: { _id: "$janr", soni: { $sum: "$soni" } } },
  { $sort: { _id: 1 } }
])
Natija
[
  { _id: 'bolalar', soni: 6 },
  { _id: 'ilmiy', soni: 1 },
  { _id: 'roman', soni: 5 }
]
JavaScript
db.sotuv.aggregate([
  { $group: { _id: { j: "$janr", f: "$filial" }, soni: { $sum: "$soni" } } },
  { $match: { "_id.f": "Namangan" } },
  { $project: { _id: "$_id.j", soni: 1 } },
  { $sort: { _id: 1 } }
])
Natija
[
  { soni: 6, _id: 'bolalar' },
  { soni: 1, _id: 'ilmiy' },
  { soni: 5, _id: 'roman' }
]

Natija bir xil, lekin ikkinchisi hamma hujjatni guruhladi va faqat keyin filtrladi.

$match ni har doim boshiga qo'ying

Bu agregatsiyadagi eng muhim optimizatsiya qoidasi, va sababi ikkita:

  1. Kamroq hujjat - keyingi bosqichlar yengillashadi.
  2. Indeks - faqat quvurning boshidagi $match indeksdan foydalana oladi. $group dan keyin kelganida indeks allaqachon ishlamaydi, chunki hujjatlar endi asl to'plamdan emas.

MongoDB ba'zi hollarda $match ni o'zi boshiga ko'chiradi, lekin buni faqat xavfsiz bo'lgan holatda qiladi. $group dan keyingi $match guruhlangan qiymatga tegishli bo'lsa, uni ko'chirib bo'lmaydi.

Xuddi shu qoida $limit uchun ham amal qiladi: agar faqat 10 ta natija kerak bo'lsa, $limit ni imkon boricha yuqoriroqqa qo'ying.

$count va $limit #

JavaScript
db.sotuv.aggregate([
  { $match: { soni: { $gte: 3 } } },
  { $count: "koplab_sotilganlar" }
])
Natija
[ { koplab_sotilganlar: 5 } ]
JavaScript
db.sotuv.aggregate([
  { $group: {
      _id: "$filial",
      tushum: { $sum: { $multiply: ["$soni", "$narx"] } }
  } },
  { $sort: { tushum: -1 } },
  { $limit: 2 }
])
Natija
[
  { _id: 'Toshkent', tushum: 923000 },
  { _id: 'Namangan', tushum: 809000 }
]

find va aggregate #

VazifaQaysi biri
Hujjatlarni topishfind
Maydonlarni tanlashfind (proyeksiya)
Saralash, cheklashIkkalasi ham
Guruhlash, yig'indiaggregate
Hisoblangan maydonaggregate
Boshqa to'plam bilan birlashtirishaggregate ($lookup)
Massivni yoyishaggregate ($unwind)

Oddiy qoida: find yetsa - find ishlating. U soddaroq va tezroq.

Amaliy topshiriq
  1. $group bilan filial bo'yicha yig'indi hisoblang.
  2. _id: null yozib, butun to'plam bo'yicha yig'indi oling.
  3. $sum: 1 va $sum: "$soni" natijalarini solishtiring.
  4. Farqni o'z so'zingiz bilan tushuntiring.
  5. $avg, $min, $max ni bitta so'rovda ishlating.
  6. $addToSet bilan har janrdagi filiallarni yig'ing.
  7. Ikkita maydon bo'yicha guruhlang.
  8. $project bilan natijani tekis ko'rinishga keltiring.
  9. $match ni boshiga va oxiriga qo'yib solishtiring.
  10. $match nega boshida bo'lishi kerakligini yozing.

Xulosa #

  • Agregatsiya - bosqichlar quvuri; har bosqich oldingisining natijasini oladi.
  • $match filtrlaydi, $group guruhlaydi, $sort saralaydi.
  • $group dagi _id - guruhlash kaliti va u majburiy.
  • _id: null butun to'plamni bitta guruhga yig'adi.
  • $sum: 1 hujjatlarni sanaydi, $sum: "$maydon" esa qiymatlarni qo'shadi.
  • $avg, $min, $max, $push, $addToSet - qolgan asosiy agregatlar.
  • Ikkita maydon bo'yicha guruhlashda _id hujjat bo'ladi: "_id.filial".
  • $project natijani tekislaydi va keraksiz maydonlarni olib tashlaydi.
  • $match ni har doim quvurning boshiga qo'ying - faqat u yerda indeks ishlaydi.
  • find yetarli bo'lsa, aggregate ishlatmang.

Keyingi bo'limda massivni yoyish va to'plamlarni birlashtirishni 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.