12-bo‘lim
Agregatsiya quvuri - asoslar
Quvur g'oyasi, $match va $group, $sum va $avg, $sort va $limit, $project hamda bosqichlar tartibining ahamiyati.
Ushbu bo‘lim mundarijasi
find savolga "qaysi hujjatlar?" deb javob beradi.
Agregatsiya esa "qancha, o'rtacha qancha, qaysi
guruhda eng ko'p" degan savollarga javob beradi.
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.
$match va $group #
Eng ko'p ishlatiladigan juftlik:
db.sotuv.aggregate([
{ $group: { _id: "$filial", jami_soni: { $sum: "$soni" } } },
{ $sort: { jami_soni: -1 } }
])
[
{ _id: 'Toshkent', jami_soni: 14 },
{ _id: 'Namangan', jami_soni: 12 },
{ _id: 'Samarqand', jami_soni: 4 }
]
$group dagi _id - guruhlash kaliti. U majburiy.
| Yozuv | Ma'nosi |
|---|---|
_id: "$filial" | Filial bo'yicha guruhla |
_id: null | Hammasini bitta guruhga |
_id: { f: "$filial", j: "$janr" } | Ikkita maydon bo'yicha |
db.sotuv.aggregate([
{ $match: { janr: "roman" } },
{ $group: {
_id: "$filial",
soni: { $sum: "$soni" },
tushum: { $sum: { $multiply: ["$soni", "$narx"] } },
ortacha_narx: { $avg: "$narx" }
} },
{ $sort: { tushum: -1 } }
])
[
{ _id: 'Toshkent', soni: 6, tushum: 547000, ortacha_narx: 83500 },
{ _id: 'Namangan', soni: 5, tushum: 383000, ortacha_narx: 74500 }
]
Agregat operatorlar #
| Operator | Nima qiladi |
|---|---|
$sum | Yig'indi ($sum: 1 - hujjatlarni sanaydi) |
$avg | O'rtacha |
$min / $max | Eng kichik / eng katta |
$first / $last | Guruhdagi birinchi / oxirgi qiymat |
$push | Hamma qiymatni massivga yig'adi |
$addToSet | Takrorlanmagan qiymatlarni massivga |
$count | Hujjatlar soni (alohida bosqich sifatida ham) |
db.sotuv.aggregate([
{ $group: {
_id: "$janr",
hujjatlar: { $sum: 1 },
eng_qimmat: { $max: "$narx" },
eng_arzon: { $min: "$narx" },
filiallar: { $addToSet: "$filial" }
} },
{ $sort: { _id: 1 } }
])
[
{
_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" farqiIkkalasi bir xil operator, lekin butunlay boshqa narsani hisoblaydi:
| Yozuv | Nimani 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 #
db.sotuv.aggregate([
{ $group: {
_id: { filial: "$filial", janr: "$janr" },
soni: { $sum: "$soni" }
} },
{ $sort: { "_id.filial": 1, "_id.janr": 1 } }
])
[
{ _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 #
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 } }
])
[
{ 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:
db.sotuv.aggregate([
{ $match: { filial: "Namangan" } },
{ $group: { _id: "$janr", soni: { $sum: "$soni" } } },
{ $sort: { _id: 1 } }
])
[
{ _id: 'bolalar', soni: 6 },
{ _id: 'ilmiy', soni: 1 },
{ _id: 'roman', soni: 5 }
]
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 } }
])
[
{ 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'yingBu agregatsiyadagi eng muhim optimizatsiya qoidasi, va sababi ikkita:
- Kamroq hujjat - keyingi bosqichlar yengillashadi.
- Indeks - faqat quvurning boshidagi
$matchindeksdan foydalana oladi.$groupdan 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 #
db.sotuv.aggregate([
{ $match: { soni: { $gte: 3 } } },
{ $count: "koplab_sotilganlar" }
])
[ { koplab_sotilganlar: 5 } ]
db.sotuv.aggregate([
{ $group: {
_id: "$filial",
tushum: { $sum: { $multiply: ["$soni", "$narx"] } }
} },
{ $sort: { tushum: -1 } },
{ $limit: 2 }
])
[
{ _id: 'Toshkent', tushum: 923000 },
{ _id: 'Namangan', tushum: 809000 }
]
find va aggregate #
| Vazifa | Qaysi biri |
|---|---|
| Hujjatlarni topish | find |
| Maydonlarni tanlash | find (proyeksiya) |
| Saralash, cheklash | Ikkalasi ham |
| Guruhlash, yig'indi | aggregate |
| Hisoblangan maydon | aggregate |
| Boshqa to'plam bilan birlashtirish | aggregate ($lookup) |
| Massivni yoyish | aggregate ($unwind) |
Oddiy qoida: find yetsa - find ishlating. U soddaroq va
tezroq.
$groupbilan filial bo'yicha yig'indi hisoblang._id: nullyozib, butun to'plam bo'yicha yig'indi oling.$sum: 1va$sum: "$soni"natijalarini solishtiring.- Farqni o'z so'zingiz bilan tushuntiring.
$avg,$min,$maxni bitta so'rovda ishlating.$addToSetbilan har janrdagi filiallarni yig'ing.- Ikkita maydon bo'yicha guruhlang.
$projectbilan natijani tekis ko'rinishga keltiring.$matchni boshiga va oxiriga qo'yib solishtiring.$matchnega boshida bo'lishi kerakligini yozing.
Xulosa #
- Agregatsiya - bosqichlar quvuri; har bosqich oldingisining natijasini oladi.
$matchfiltrlaydi,$groupguruhlaydi,$sortsaralaydi.$groupdagi_id- guruhlash kaliti va u majburiy._id: nullbutun to'plamni bitta guruhga yig'adi.$sum: 1hujjatlarni sanaydi,$sum: "$maydon"esa qiymatlarni qo'shadi.$avg,$min,$max,$push,$addToSet- qolgan asosiy agregatlar.- Ikkita maydon bo'yicha guruhlashda
_idhujjat bo'ladi:"_id.filial". $projectnatijani tekislaydi va keraksiz maydonlarni olib tashlaydi.$matchni har doim quvurning boshiga qo'ying - faqat u yerda indeks ishlaydi.findyetarli bo'lsa,aggregateishlatmang.
Keyingi bo'limda massivni yoyish va to'plamlarni birlashtirishni 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.