MongoDB’da sxema loyihalash: joylash yoki havola
Amaliyot3 daqInnovialabs tahririyati
Qisqacha
Birga o‘qiladigan va hajmi cheklangan ma’lumotlarni hujjat ichiga joylang, umumiy, katta yoki cheksiz o‘sadigan ma’lumotlarga havola qiling, sxemani esa eng ko‘p bajariladigan so‘rovlar atrofida quring.
Qoida bitta xatboshida
MongoDB’da sxema abstrakt obyektlar atrofida emas, ilova ma’lumotlarni qanday o‘qishi va yozishi atrofida loyihalanadi. Ma’lumot ota hujjat bilan birga o‘qilsa, faqat unga tegishli bo‘lsa va kichik bo‘lib qolsa, uni hujjat ichiga joylang (embedding). Ma’lumot ko‘p hujjatlar uchun umumiy bo‘lsa, mustaqil o‘zgarsa, katta bo‘lsa yoki cheksiz o‘sishi mumkin bo‘lsa, unga _id orqali havola qiling (referencing).
Joylash va havola: taqqoslash
| Savol | Joylash | Havola |
|---|---|---|
| Ota hujjat bilan birga o‘qiladimi? | Deyarli doim | Ko‘pincha alohida |
| Bitta ota hujjatga tegishlimi? | Ha | Ko‘pchilik foydalanadi |
| Hajmi cheklanganmi? | Kichik, chegarasi bor | Vaqt o‘tishi bilan o‘sadi |
| Mustaqil o‘zgaradimi? | Kamdan-kam | Tez-tez |
| Voqea paytidagi holat kerakmi? | Ha, nusxasini joylaymiz | — |
Hujjat hajmining qat’iy limitini — 16 MB — yodda tuting. Unga yetmasdan ancha oldin katta hujjatlar har bir o‘qish va yangilashni sekinlashtiradi.
Model: foydalanuvchilar, mahsulotlar, buyurtmalar
Foydalanuvchilar
Manzillar va bildirishnoma sozlamalari kam va doim profil bilan birga o‘qiladi — joylaymiz.
{
_id: ObjectId("..."),
email: "user@example.com",
name: "Aziza",
addresses: [
{ label: "home", city: "Tashkent", street: "..." }
],
settings: { language: "uz", notifications: true }
}
Buyurtmalarni foydalanuvchi ichiga joylamaymiz: ularning soni cheksiz o‘sadi.
Mahsulotlar
Mahsulotdan ko‘plab buyurtmalar va savatlar foydalanadi, shuning uchun u alohida kolleksiyada turadi. Kategoriyaga qarab o‘zgaradigan xususiyatlarni ichki obyektda saqlash qulay.
{
_id: ObjectId("..."),
sku: "TSHIRT-001",
title: "Futbolka",
price: 120000,
categoryId: ObjectId("..."),
attributes: { size: ["S", "M", "L"], color: "black" },
stock: 42
}
Buyurtmalar
Buyurtma foydalanuvchiga havola qiladi, lekin pozitsiyalarning xarid paytidagi holatini joylaydi: nomi va narxi. Ertaga mahsulot narxi o‘zgarsa, eski buyurtma o‘zgarmasligi kerak.
{
_id: ObjectId("..."),
userId: ObjectId("..."),
status: "paid",
createdAt: ISODate("..."),
items: [
{ productId: ObjectId("..."), title: "Futbolka", price: 120000, qty: 2 }
],
total: 240000,
shipping: { city: "Tashkent", street: "..." }
}
Bu extended reference patterni: bog‘lanish uchun _id saqlanadi va ko‘rsatish uchun kerakli bir nechta maydon nusxalanadi.
Cheksiz massivlardan qoching
Chegarasiz o‘sadigan massiv — postdagi barcha izohlar, qurilmaning barcha hodisalari, foydalanuvchining barcha buyurtmalari — MongoDB’dagi eng ko‘p uchraydigan xato. Bu ulkan hujjatlar, sekin yangilanishlar va hajm limitiga yetib qolish xavfiga olib keladi.
Uning o‘rniga:
- Ota hujjatga havolali alohida kolleksiya:
postIdmaydoni va unga indekslicomments. - Subset patterni: faqat oxirgi bir nechta elementni (masalan, yangi sharhlarni) joylaymiz, to‘liq ro‘yxat esa alohida saqlanadi.
- Vaqt qatorlari uchun bucket patterni: hodisalarni har bir qurilma uchun soatlik yoki kunlik bitta hujjatga guruhlaymiz.
Murojaat stsenariylari uchun indekslar
Avval asosiy so‘rovlarni yozib chiqing, keyin ular uchun indeks yarating.
db.orders.createIndex({ userId: 1, createdAt: -1 }) // foydalanuvchi buyurtmalari tarixi
db.orders.createIndex({ status: 1, createdAt: -1 }) // admin panelda holat bo‘yicha ro‘yxat
db.products.createIndex({ sku: 1 }, { unique: true })
db.users.createIndex({ email: 1 }, { unique: true })
Amaliy qoidalar:
- Tarkibiy indekslarda ESR tartibiga rioya qiling: aniq moslik maydonlari (Equality), keyin saralash (Sort), keyin oraliq (Range).
- Massivlar bo‘yicha indekslar (multikey) ishlaydi, lekin katta massivlar ularni og‘irlashtiradi.
- So‘rovlarni
explain("executionStats")orqali tekshiring:COLLSCANemas,IXSCANbo‘lishi kerak. - Har bir indeks yozishni sekinlashtiradi va xotira egallaydi — ishlatilmaydiganlarini o‘chiring.
Ko‘p uchraydigan xatolar
- Relyatsion sxemani aynan ko‘chirish va JOIN’ni ko‘plab
$lookuporqali taqlid qilish. - Umumiy ma’lumotlarni (masalan, butun mahsulotni) hamma joyga joylash, keyin minglab nusxalarni yangilashga majbur bo‘lish.
- Pulni butun sonlarda minimal birlikda yoki
Decimal128o‘rniga suzuvchi nuqtali sonlarda saqlash. - Validatsiyadan voz kechish: MongoDB kolleksiyalar uchun
$jsonSchemavalidatorlarini qo‘llaydi.