Mundarija (28)
- Bu darsda
- 1. Nega bu kerak?
- 2. Schema: hujjatning tavsifi
- 2.1 Birinchi schema
- 2.2 SchemaTypes — turlar
- 2.3 Vazifa schema'si: hamma qoida birga
- 2.4 timestamps
- 3. Model: schema + kolleksiya
- 3.1 mongoose.model()
- 3.2 Tuzoq: kolleksiya nomi
- 4. Validatsiya: xatolarni o'qish
- 4.1 Hamma xato birdan
- 4.2 Bazasiz validatsiya
- 4.3 unique — validator emas
- 4.4 CastError — tur mos kelmasa
- 5. strict: sxemada yo'q maydon
- 5.1 Sukut — jim tashlash
- 5.2 strict: "throw"
- 6. Indekslar va autoIndex
- 7. Loyiha qadami: kanon tajribasi, loyihaga kirmaydi
- 8. Ko'p uchraydigan xatolar
- 9. Mashqlar
- 1-mashq (oson): to'ldiring
- 2-mashq (o'rta): hamma xato birdan
- 3-mashq (qiyin): setter, default va strict
- 10. Real ishda
- Xulosa
- Manbalar
Mongoose schema va model: sxemasiz MongoDB'ga tartib olib kirish
Qisqacha: Mongoose — MongoDB drayveri ustidagi kutubxona: schema hujjat shaklini va qoidalarini (tur,
required,default,enum, validator) yozadi, model shu schema bilan kolleksiyaga ishlaydi. Tekshiruv bazada emas, ilovada bo'ladi — bittacreatehamma xatoni birdan qaytaradi. Uchta tuzoq: model nomidan kolleksiya nomi inglizcha ko'plik bilan yasaladi (Vazifa→vazifas), sxemada yo'q maydon jim tashlanadi (strict),uniqueesa validator emas — uni bazadagi indeks tekshiradi (E11000).
Bu darsda
- Mongoose nima uchun kerakligini va drayverdan farqini tushuntira olasiz.
- Schema yozasiz: turlar,
required,default,enum,min/max,trim/lowercase, custom validator,timestamps. model()bilan model yaratasiz va kolleksiya nomi tuzog'ini chetlab o'tasiz.- Validatsiya xatolarini o'qiysiz:
ValidationError,CastError,E11000. strictrejimining jim xulqini vastrict: "throw"ni bilasiz.
Oldin bilishingiz kerak: MongoDB native driver, MongoDB tuzilishi va vositalari, Validatsiya: nima uchun, qayerda va qanday, CREATE TABLE va cheklovlar.
1. Nega bu kerak?
MongoDB tuzilishi darsida kanon vazifalar kolleksiyasiga matn: 42 yozdi — Mongo indamadi. Native driver darsida esa replaceOne hujjatning yarmini jim o'chirdi. Ikkalasining ildizi bitta: bazada sxema yo'q.
Postgres'da bu ishni CREATE TABLE qilardi: text NOT NULL, CHECK (length(matn) <= 100), enum turi (CREATE TABLE va cheklovlar). Mongo'da bunday joy yo'q. Demak, tartibni ilova o'zi saqlashi kerak.
Mongoose — shu ishni qiladigan kutubxona. U MongoDB rasmiy drayveri ustiga qurilgan va uchta narsa qo'shadi:
- Schema — hujjat qanday ko'rinishi kerakligining tavsifi.
- Validatsiya — saqlashdan oldin qoidalarni tekshirish.
- Model — schema bilan bog'langan kolleksiya ustidagi qulay metodlar (keyingi darslarda: CRUD, populate, middleware).
O'xshatish: bo'sh daftar — har kim xohlagan narsani yozadi. Ish hujjati blankasi esa katakchalarga bo'lingan: "ism — majburiy", "sana — kun.oy.yil", "lavozim — ro'yxatdan tanlang". Mongoose — daftarga blanka chizib beradi. Daftar (Mongo) baribir hamma narsani qabul qiladi, lekin blankadan o'tmagan narsa unga yetib bormaydi.
Bu darsdagi chiqishlar ikki manbadan: kanon tajribasi (Node 24.21.0, mongoose 9.11.2, MongoDB 8.3.13 Docker'da) va bazasiz sinovlarimiz ("biz ishga tushirdik" — xuddi shu mongoose 9.11.2, Node 24.21.0, ulanishsiz).
2. Schema: hujjatning tavsifi
2.1 Birinchi schema
O'rnatish (o'z loyihangizda):
npm i --save-exact mongoose@9.11.2Kanon vazifalar uchun yozgan foydalanuvchi schema'si:
import mongoose from "mongoose";
const { Schema } = mongoose;
const FoydalanuvchiS = new Schema({
email: {
type: String, required: true, lowercase: true, trim: true,
unique: true, match: /^[^@\s]+@[^@\s]+$/,
},
ism: {
type: String, required: [true, "ism majburiy"],
maxlength: 100,
},
}, {
timestamps: { createdAt: "yaratilgan", updatedAt: "yangilangan" },
});Schema — oddiy obyekt: kalit — maydon nomi, qiymat — qoidalar. Birinchi argument — maydonlar, ikkinchisi — schema sozlamalari (bu yerda timestamps).
2.2 SchemaTypes — turlar
| Mongoose turi | JavaScript qiymati | Misol |
|---|---|---|
String |
satr | matn |
Number |
son | versiya |
Boolean |
true/false |
bajarildi |
Date |
Date |
muddat |
Schema.Types.ObjectId |
ObjectId | egasi |
[String] |
satrlar massivi | teglar |
[IzohS] |
ichki hujjatlar massivi | izohlar |
Schema.Types.Decimal128 |
aniq kasr | narx |
Map, Schema.Types.Mixed |
erkin obyekt | sozlamalar |
Qisqa yozuv ham bor: ism: String — ism: { type: String } bilan bir xil. Qoida qo'shish kerak bo'lsa — to'liq shakl.
Mixed — "nima bo'lsa ham" turi: Mongoose uni tekshirmaydi. JSONB darsidagi erkin sozlamalar uchun mos, lekin ko'p ishlatsangiz — sxemaning foydasi yo'qoladi.
2.3 Vazifa schema'si: hamma qoida birga
Kanon vazifa schema'si (qatorlar telefon uchun bo'lingan, mazmuni aynan):
const IzohS = new Schema({
muallif: { type: Schema.Types.ObjectId, ref: "Foydalanuvchi" },
matn: { type: String, required: true, maxlength: 2000 },
}, { timestamps: { createdAt: "yaratilgan", updatedAt: false } });
const VazifaS = new Schema({
egasi: {
type: Schema.Types.ObjectId, ref: "Foydalanuvchi",
required: true, index: true,
},
matn: {
type: String, required: true, trim: true,
minlength: 1, maxlength: 100,
validate: {
validator: (m) => !/\s{2,}/.test(m),
message: (p) => `"${p.value}" — ketma-ket bo'shliq bo'lmasin`,
},
},
bajarildi: { type: Boolean, default: false },
ustuvorlik: {
type: String,
enum: {
values: ["past", "orta", "yuqori"],
message: "{VALUE} — ustuvorlik emas",
},
default: "orta",
},
teglar: { type: [String], default: [] },
izohlar: { type: [IzohS], default: [] },
versiya: { type: Number, default: 1, min: 1 },
}, {
timestamps: { createdAt: "yaratilgan", updatedAt: "yangilangan" },
});Har qoidani alohida ko'ramiz:
| Qoida | Nima qiladi | Postgres o'xshashi |
|---|---|---|
required: true |
bo'sh qolsa xato | NOT NULL |
default: "orta" |
berilmasa shu qiymat | DEFAULT 'orta' |
enum: [...] |
faqat ro'yxatdagilar | enum turi yoki CHECK (… IN …) |
min, max |
son chegarasi | CHECK (versiya >= 1) |
minlength, maxlength |
satr uzunligi | CHECK (length(…) <= 100) |
match: /…/ |
regex'ga mos bo'lsin | CHECK (… ~ '…') |
trim, lowercase |
saqlashdan oldin o'zgartiradi | trigger (Triggerlar) |
validate |
o'z funksiyangiz | CHECK + funksiya |
index: true, unique: true |
indeks yaratadi | CREATE INDEX, UNIQUE |
ref: "Foydalanuvchi" — "bu ObjectId Foydalanuvchi modelining hujjatiga ishora". Mongo buni tekshirmaydi — tashqi kalit emas. U populate uchun kerak.
izohlar: [IzohS] — ichki hujjat (subdocument): har izoh o'z schema'si bilan tekshiriladi va o'z _id sini oladi.
Xabarlar ikki shaklda: required: [true, "ism majburiy"] (massiv — qiymat va xabar) yoki enum: { values, message }. {VALUE} — Mongoose noto'g'ri qiymatni shu joyga qo'yadi. Custom validator'da message funksiya bo'lishi mumkin: p.value — tekshirilgan qiymat.
2.4 timestamps
timestamps: true bo'lsa, Mongoose har hujjatga createdAt va updatedAt qo'shadi va o'zi yangilaydi. Kanon o'zbekcha nomlarni berdi: { createdAt: "yaratilgan", updatedAt: "yangilangan" }. Izohda updatedAt: false — izoh tahrirlanmaydi, yangilanish vaqti kerak emas.
Kanon Azizni yaratib, hujjat kalitlarini chiqardi:
const aziz = await Foydalanuvchi.create({
email: " AZIZ@Example.com ", ism: "Aziz Karimov",
});
console.log("lowercase+trim:", aziz.email, "| timestamps:",
Object.keys(aziz.toObject()).join(", "));lowercase+trim: aziz@example.com | timestamps: email, ism, _id, yaratilgan, yangilangan, __vIkki narsa: " AZIZ@Example.com " saqlashdan oldin aziz@example.com ga aylandi (trim + lowercase). Va hujjatda biz bermagan to'rtta maydon paydo bo'ldi: _id (ObjectId), yaratilgan, yangilangan va __v. __v — Mongoose'ning versiya kaliti (versionKey): massiv o'zgarishlarida ziddiyatni sezish uchun. Uni Mongoose ilg'or darsida ko'ramiz.
Tekshirib ko'ring: Schema'da
lowercase: truebor. FoydalanuvchiAziz@EXAMPLE.combilan login qilmoqchi. Qidiruv filtrida nima qilish kerak?
Javob
Mongoose orqali — hech narsa qilish shart emas: u trim va lowercase ni filtrga ham qo'llaydi. Biz bazasiz tekshirdik (mongoose 9.11.2): find({ email: " Aziz@EXAMPLE.com " }) ning filtri {"email":"aziz@example.com"} ga aylandi. Lekin xuddi shu filtr drayver yoki mongosh orqali yuborilsa — o'zgarmaydi va hech narsa topilmaydi. Shuning uchun ishonchli yo'l — kirishni o'zingiz normallashtirish (email.trim().toLowerCase()): qaysi vosita bilan qidirmang, natija bir xil.
3. Model: schema + kolleksiya
3.1 mongoose.model()
await mongoose.connect(MONGO_URL);
const Foydalanuvchi = mongoose.model("Foydalanuvchi", FoydalanuvchiS);
const Vazifa = mongoose.model("Vazifa", VazifaS);
await Foydalanuvchi.init();mongoose.connect(url) — bitta umumiy ulanish (ichida drayverning MongoClient va hovuzi — oldingi darsdagi "bitta client" qoidasi Mongoose'da o'zi bajariladi). model(nom, schema) — model sinfi: new Vazifa({...}) hujjat yaratadi, Vazifa.find(...) qidiradi.
Foydalanuvchi.init() — kanon izohi bilan: "unique indeks yaratilishini kutish (aks holda birinchi takror o'tib ketishi mumkin)". Mongoose indekslarni fonda yaratadi. Indeks tayyor bo'lmasdan takror email yozilsa — baza uni tekshira olmaydi.
3.2 Tuzoq: kolleksiya nomi
Kanon model yaratgandan keyin kolleksiya nomlarini chiqardi:
to'plam nomlari (model nomidan, ko'plik + kichik harf): foydalanuvchis vazifasfoydalanuvchis! Mongoose model nomini kichik harfga o'tkazib, inglizcha ko'plik qo'shimchasini qo'shadi. U o'zbek tilini bilmaydi. Biz bazasiz sinab ko'rdik — model nomidan kolleksiya nomi:
const s = () => new Schema({ nom: String });
const nomlar = [
model("Vazifa", s()),
model("Foydalanuvchi", s()),
model("Person", s()),
model("Izoh", s(), "izohlar"),
].map((M) => `${M.modelName} → ${M.collection.collectionName}`);
console.log(nomlar.join("\n"));Natija (biz ishga tushirdik: mongoose 9.11.2, Node 24.21.0, ulanishsiz):
Vazifa → vazifas
Foydalanuvchi → foydalanuvchis
Person → people
Izoh → izohlarPerson → people — inglizcha qoidalar lug'ati ishladi. O'zbekcha nomlarga esa shunchaki s qo'shildi. Oxirgisida uchinchi argument — kolleksiya nomini aniq berdik.
Nega bu muhim? Native driver darsida kanon ma'lumotni vazifalar kolleksiyasiga yozgan edi. Mongoose modeli esa vazifas ni qidiradi — bo'sh kolleksiyani. Xato yo'q, natija bo'sh. Bir loyihada drayver va Mongoose aralash ishlatilsa — ikki xil kolleksiya paydo bo'ladi.
Yechim — nomni har doim aniq bering:
const Vazifa = mongoose.model("Vazifa", VazifaS, "vazifalar");
// yoki schema sozlamasida:
new Schema({ /* … */ }, { collection: "vazifalar" });Diqqat: Bu darsdagi kanon tajribasi alohida
mongoosebazasida ishladi va nomni ataylab bermadi — tuzoqni ko'rsatish uchun. Keyingi darslardagi kanon chiqishlaridavazifas,foydalanuvchisnomlarini ko'rasiz — shu sababdan.
4. Validatsiya: xatolarni o'qish
4.1 Hamma xato birdan
Kanon ataylab uchta qoidani buzgan vazifa yaratdi: ikki bo'shliqli matn, noma'lum ustuvorlik, versiya: 0:
try {
await Vazifa.create({
egasi: aziz._id, matn: "a b", ustuvorlik: "juda", versiya: 0,
});
} catch (x) {
console.log(x.name, "→", Object.entries(x.errors)
.map(([k, e]) => `${k}: ${e.message}`).join(" | "));
}ValidationError → matn: "a b" — ketma-ket bo'shliq bo'lmasin | ustuvorlik: juda — ustuvorlik emas | versiya: Path `versiya` (0) is less than minimum allowed value (1).Bitta ValidationError, ichida errors obyekti — har buzilgan maydon uchun bittadan. Ikkitasida bizning o'zbekcha xabarlarimiz, uchinchisida (min) — Mongoose'ning sukut inglizcha xabari: "versiya yo'li (0) ruxsat etilgan eng kichik qiymatdan (1) kichik". Hujjat bazaga umuman yuborilmadi.
Bu API uchun qulay: foydalanuvchiga birinchi xatoni emas, hammasini birdan ko'rsatasiz (Zod dagi issues ro'yxati kabi).
Ikkinchi sinov — majburiy maydonlarsiz:
try { await Vazifa.create({ matn: "" }); }
catch (x) {
console.log(x.name, "→", Object.keys(x.errors).sort().join(", "));
}ValidationError → egasi, matnmatn: "" — bo'sh satr ham required ni buzadi.
4.2 Bazasiz validatsiya
Mongoose validatsiyasi ilovada ishlaydi — bazaga ulanmasdan ham tekshirish mumkin. Biz shuni sinadik: ulanishsiz, validate() bilan (qisqartirilgan schema):
const yomon = new Vazifa({
matn: " Non olish ",
ustuvorlik: "juda",
versiya: 0,
nomalum: "yo'qoladi",
});
try {
await yomon.validate();
} catch (xato) {
console.log(xato.name);
for (const [yol, e] of Object.entries(xato.errors)) {
console.log(`- ${yol}: ${e.message}`);
}
}
console.log(yomon.matn, "|", yomon.nomalum);Natija (biz ishga tushirdik: mongoose 9.11.2, Node 24.21.0, ulanishsiz):
ValidationError
- egasi: Path `egasi` is required.
- ustuvorlik: `juda` is not a valid enum value for path `ustuvorlik`.
- versiya: Path `versiya` (0) is less than minimum allowed value (1).
Non olish | undefinedUchta kuzatuv:
enumuchun o'z xabarimizni bermadik — Mongoose sukut xabari: "juda—ustuvorlikyo'li uchun ruxsat etilgan enum qiymati emas".matnhujjat yaratilgandayoq"Non olish"bo'ldi —trimqiymat berilganda ishlaydi, saqlashda emas.nomalum—undefined. Sxemada yo'q maydon jim tashlandi (bustrictrejim — pastda).
Maslahat: Sinovimizda
validateSync()ni ham chaqirdik — Mongoose 9.11.2 ogohlantirdi:`Document.prototype.validateSync()` is deprecated and will be removed in Mongoose 10. Use `Document.prototype.validate()` instead.Ya'ni sinxron variant eskirgan, keyingi katta versiyada o'chiriladi. Yangi koddaawait doc.validate().
4.3 unique — validator emas
Takror email bilan foydalanuvchi:
try {
await Foydalanuvchi.create({
email: "aziz@example.com", ism: "Takror",
});
} catch (x) {
console.log("unique — bu VALIDATOR emas, Mongo xatosi:",
x.name, x.code);
}unique — bu VALIDATOR emas, Mongo xatosi: MongoServerError 11000Ko'ryapsizmi: ValidationError emas, MongoServerError kodi 11000 (E11000 duplicate key error). unique: true Mongoose'ga "bu maydonga noyob indeks yarat" degan buyruq, xolos. Tekshiruvni bazadagi indeks qiladi — hujjat serverga borgandan keyin.
flowchart LR
A["create(obyekt)"] --> B["cast: tur"]
B --> C["trim, lowercase, default"]
C --> D{"validate"}
D -- xato --> E["ValidationError"]
D -- ok --> F["MongoDB: insert"]
F -- takror --> G["E11000 (unique indeks)"]
F -- ok --> H["saqlandi"]Diagrammaga qarang: chap qism — ilova ichida, o'ng qism — serverda. Xatolar ham ikki joydan keladi, demak API'dagi xato ishlovchida ikkalasini ushlash kerak: ValidationError → 400, code === 11000 → 409 (Global error handler).
4.4 CastError — tur mos kelmasa
await Vazifa.findById("123").catch((x) =>
`${x.name}: ${x.message.slice(0, 80)}`);cast xatosi: CastError: Cast to ObjectId failed for value "123" (type string) at path "_id" for model "V(Kanon xabarni 80 belgida kesgan.) Tarjima: "_id yo'lida "123" qiymatini ObjectId'ga aylantirib bo'lmadi". Mongoose filtr qiymatlarini ham schema turiga aylantiradi (cast): "6add9a83…" kabi 24 belgili satr ObjectId bo'ladi, "123" — bo'lmaydi.
Amaliy natija: GET /vazifalar/123 ga 500 emas, 400 yoki 404 qaytarish kerak. CastError ni ushlang yoki id'ni oldindan tekshiring (mongoose.isValidObjectId(id)).
5. strict: sxemada yo'q maydon
5.1 Sukut — jim tashlash
const v1 = await Vazifa.create({
egasi: aziz._id, matn: "Non olish #uy #Bozor",
nomalum: "yo'qoladi",
});
await Vazifa.collection.findOne(
{ _id: v1._id },
{ projection: { _id: 0, matn: 1, teglar: 1, nomalum: 1 } },
);Vazifa.collection — Mongoose'ni chetlab, drayverning o'z kolleksiyasi: bazada haqiqatan nima borligini ko'rish uchun.
saqlangan: {"matn":"Non olish #uy #Bozor","teglar":["uy","bozor"]}nomalum yo'q — xato ham yo'q. Bu sukut strict: true rejimi: "sxemada yo'q maydonni bazaga yozma". Himoya sifatida yaxshi (foydalanuvchi isAdmin: true yuborsa, u yozilmaydi). Lekin xatoni ham yashiradi: maydon nomida xato qilsangiz (ustuvorlk), ma'lumot jim yo'qoladi.
(teglar matndan avtomatik ajratildi — bu kanonning pre("save") middleware'i, Mongoose ilg'or darsida.)
5.2 strict: "throw"
const StrictThrow = mongoose.model("StrictThrow",
new Schema({ a: String }, { strict: "throw" }));
await StrictThrow.create({ a: "x", b: 1 })
.then(() => "o'tdi", (x) => x.name);strict: 'throw' → StrictModeErrorEndi noma'lum maydon xato beradi. Qaysi biri yaxshi? Ichki API'da, kirish allaqachon Zod bilan tekshirilgan bo'lsa — throw dasturchi xatosini darhol ko'rsatadi. Tashqi kirishni to'g'ridan modelga bermang — avval validatsiya (Validatsiya: nima uchun, qayerda), keyin faqat kerakli maydonlar.
Tekshirib ko'ring: Foydalanuvchi profilini yangilash so'roviga hujumchi
{"ism": "Ali", "rol": "admin"}yubordi. Schema'darolyo'q,strictsukut. Nima bo'ladi? Agar schema'darolbo'lsa-chi?
Javob
rol sxemada bo'lmasa — jim tashlanadi, faqat ism yoziladi. Lekin schema'da rol bor bo'lsa (foydalanuvchida haqiqatan rol maydoni bor), strict himoya qilmaydi — rol: "admin" yoziladi! Bu mass assignment zaifligi. To'g'risi: so'rov tanasidan faqat ruxsat etilgan maydonlarni ajratib olish ({ ism } = body) yoki Zod schema'si bilan qat'iy shakl.
6. Indekslar va autoIndex
Schema'dagi index: true va unique: true — indeks e'lonlari. Mongoose ularni model birinchi ishlatilganda yaratadi (autoIndex). Kanon vazifalar kolleksiyasining indekslarini o'qidi:
{"_id":1} {"egasi":1} | __v: 0_id — har doim bor, egasi — index: true dan. Qulay, lekin prodakshnda xavfli: katta kolleksiyada indeks yaratish ancha vaqt va resurs oladi, va u ilova ishga tushganda kutilmaganda boshlanadi. Mongoose hujjati prodakshnda autoIndex: false qilib, indekslarni alohida (migratsiya kabi) yaratishni tavsiya qiladi (Migratsiya tushunchasi bilan bir xil g'oya). Indekslarning o'zi — MongoDB indekslari darsida.
7. Loyiha qadami: kanon tajribasi, loyihaga kirmaydi
vazifalar-api Postgres'da qoladi va unda validatsiyani Zod qiladi (25-qism). Commit yo'q. Kanon bu darsda (kanon o'lchovi, IlmHamroh, 2026-10):
- Foydalanuvchi va vazifa schema'larini
vazifalarqoidalari bilan yozdi (matn ≤ 100, ustuvorlik enum'i, versiya ≥ 1). - Kolleksiya nomi tuzog'ini qayd qildi:
foydalanuvchis,vazifas. - Bitta
createda hamma validatsiya xatosi,unique→ 11000,CastError,strictjim vathrow.
Biz bunga bazasiz ikki sinov qo'shdik: kolleksiya nomlari (Person → people) va validate(), hamda validateSync() eskirgani haqidagi ogohlantirish.
Postgres bilan solishtiring: u yerda bu qoidalarning hammasi bazada (CHECK, NOT NULL, UNIQUE) va har qanday mijozni — psql'ni ham — to'xtatadi. Mongoose qoidalari esa faqat Mongoose orqali yozilganda ishlaydi. mongosh yoki drayver bilan yozilgan hujjat ularni chetlab o'tadi.
8. Ko'p uchraydigan xatolar
| Xato | Oqibat | To'g'risi |
|---|---|---|
| Kolleksiya nomini bermaslik | vazifas — mavjud ma'lumot "yo'qoladi" |
3-argument yoki collection sozlamasi |
unique ni validator deb o'ylash |
11000 xatosi ushlanmaydi, 500 | code === 11000 → 409 |
Maydon nomida xato (ustuvorlk) |
strict jim tashlaydi |
strict: "throw" yoki Zod |
findById ga noto'g'ri id |
CastError → 500 |
isValidObjectId yoki 400 |
| Mongoose qoidalarini "bazadagi" deb hisoblash | mongosh/drayver bilan yozilgan yomon hujjat | Kritik qoidaga $jsonSchema yoki faqat Mongoose orqali yozish |
validateSync() |
Mongoose 10 da o'chadi | await doc.validate() |
init() siz unique test |
Birinchi takror o'tib ketishi mumkin | await Model.init() |
9. Mashqlar
Mashqlar kurs/mashqlar/27/44-mongoose-schema/ da. 2- va 3-mashq yechimlari Node 24 da tekshirilgan (biz ishga tushirdik — Mongoose qoidalarining kichik modeli, kutubxonasiz).
1-mashq (oson): to'ldiring
- Berilmasa qo'yiladigan qiymat —
- Faqat ro'yxatdagi qiymatlarga ruxsat —
createdAt/updatedAtni qo'shadigan sozlama —- Takror email xatosining kodi —
model("Vazifa", schema)qaysi kolleksiyani ishlatadi?
Yechim
- default —
default: "orta". - enum —
enum: { values: [...], message }. - timestamps — nomlarini o'zgartirish mumkin:
{ createdAt: "yaratilgan" }. - 11000 —
MongoServerError, unique indeksdan; validator emas. - vazifas — kichik harf + inglizcha ko'plik; 3-argument bilan
vazifalarqiling.
2-mashq (o'rta): hamma xato birdan
Mongoose validatsiyasining kichik modelini yozing. tekshir(qiymatlar, sxema) — xatolar obyektini qaytarsin ({ maydon: xabar }), xato bo'lmasa null. Qoidalar: required, enum, min, maxlength. Bitta maydonda bir nechta qoida buzilsa — birinchisi yetadi, lekin hamma maydonlar tekshirilsin. Xabarlar — Mongoose sukut xabarlari kabi.
Ishora: for…of Object.entries(sxema) va har maydonda qoidalarni tartib bilan tekshirish.
Yechim
function tekshir(q, sxema) {
const xatolar = {};
for (const [yol, r] of Object.entries(sxema)) {
const v = q[yol];
if (v === undefined || v === null || v === "") {
if (r.required) xatolar[yol] = `Path \`${yol}\` is required.`;
continue;
}
if (r.enum && !r.enum.includes(v)) {
xatolar[yol] =
`\`${v}\` is not a valid enum value for path \`${yol}\`.`;
} else if (r.min !== undefined && v < r.min) {
xatolar[yol] = `Path \`${yol}\` (${v}) is less than `
+ `minimum allowed value (${r.min}).`;
} else if (r.maxlength !== undefined && v.length > r.maxlength) {
xatolar[yol] = `Path \`${yol}\` (\`${v}\`, length ${v.length})`
+ ` is longer than the maximum allowed length`
+ ` (${r.maxlength}).`;
}
}
return Object.keys(xatolar).length ? xatolar : null;
}
const sxema = {
egasi: { required: true },
matn: { required: true, maxlength: 100 },
ustuvorlik: { enum: ["past", "orta", "yuqori"] },
versiya: { min: 1 },
};
const xatolar = tekshir(
{ matn: "Non olish", ustuvorlik: "juda", versiya: 0 }, sxema);
for (const [yol, x] of Object.entries(xatolar)) {
console.log(`- ${yol}: ${x}`);
}
const qisqa = { matn: { maxlength: 5 } };
console.log(tekshir({ matn: "Bozorga" }, qisqa).matn);
console.log(tekshir({ egasi: "a1", matn: "Non" }, sxema));Konsolda:
- egasi: Path `egasi` is required.
- ustuvorlik: `juda` is not a valid enum value for path `ustuvorlik`.
- versiya: Path `versiya` (0) is less than minimum allowed value (1).
Path `matn` (`Bozorga`, length 7) is longer than the maximum allowed length (5).
nullBirinchi to'rt qator haqiqiy Mongoose xabarlari bilan aynan bir xil: uchtasi — «Bazasiz validatsiya» bo'limidagi chiqish, to'rtinchisini biz alohida tekshirdik (mongoose 9.11.2, maxlength: 5, qiymat "Bozorga"). Asosiy g'oya: tekshiruv birinchi xatoda to'xtamaydi — hamma maydon aylanib chiqiladi.
3-mashq (qiyin): setter, default va strict
tayyorla(kirish, sxema, strict) funksiyasini yozing — Mongoose hujjat yaratishdan oldin qiladigan ishning modeli:
trim: true— satrni qirqish,lowercase: true— kichik harf.- Berilmagan maydonga
default(funksiya bo'lsa — chaqirib). - Sxemada yo'q maydon:
strict === true— tashlash;strict === "throw"—StrictModeErrornomli xato tashlash.
Kanon misoli bilan sinang: " AZIZ@Example.com " → aziz@example.com.
Ishora: xato nomini berish uchun const x = new Error(…); x.name = "StrictModeError";.
Yechim
function tayyorla(kirish, sxema, strict = true) {
const natija = {};
for (const [k, v] of Object.entries(kirish)) {
if (!(k in sxema)) {
if (strict === "throw") {
const x = new Error(`Field \`${k}\` is not in schema`);
x.name = "StrictModeError";
throw x;
}
continue;
}
let q = v;
if (typeof q === "string" && sxema[k].trim) q = q.trim();
if (typeof q === "string" && sxema[k].lowercase) {
q = q.toLowerCase();
}
natija[k] = q;
}
for (const [k, r] of Object.entries(sxema)) {
if (natija[k] === undefined && "default" in r) {
natija[k] = typeof r.default === "function"
? r.default() : r.default;
}
}
return natija;
}
const sxema = {
email: { trim: true, lowercase: true },
ism: { trim: true },
rol: { default: "oddiy" },
teglar: { default: () => [] },
};
console.log(tayyorla({
email: " AZIZ@Example.com ", ism: " Aziz ", nomalum: 1,
}, sxema));
try {
tayyorla({ email: "a@example.com", b: 1 }, sxema, "throw");
} catch (x) {
console.log(x.name, "—", x.message);
}Konsolda:
{ email: 'aziz@example.com', ism: 'Aziz', rol: 'oddiy', teglar: [] }
StrictModeError — Field `b` is not in schemateglar uchun default — funksiya: aks holda hamma hujjat bitta massivni bo'lishib qolardi (havola semantikasi). Mongoose ham massiv va obyekt default'larini har hujjat uchun alohida yaratadi.
10. Real ishda
- Mongoose — Node'dagi eng ko'p ishlatiladigan MongoDB kutubxonasi; Express + Mongo loyihalarining aksariyatida schema va modellar shu yerda yoziladi. NestJS'da ham
@nestjs/mongooseorqali (Mongoose bilan NestJS darsida). - Xato ishlovchida ikki manba:
ValidationError(400) vaMongoServerError 11000(409) — ko'p loyihalarda aynan ikkinchisi unutiladi. - Kolleksiya nomi — eski loyihalarda
users,peoplekabi avtomatik nomlar ko'p uchraydi. O'zbekcha model nomida doim aniq nom bering. - Intervyu savollari: "Mongoose validatsiyasi bazadami yoki ilovadami?", "
uniquevalidatormi?", "strictnima qiladi?".
Xulosa
- Mongoose — drayver ustidagi qavat: schema (shakl va qoidalar) + model (kolleksiya bilan ishlash); kanon versiyasi 9.11.2.
- Qoidalar:
required,default,enum,min/max,minlength/maxlength,match,trim/lowercase, customvalidate,timestamps. - Validatsiya ilovada: bitta
ValidationErrorichida hamma xato;CastError— tur mos kelmasa;validateSync()eskirgan —validate(). unique— indeks, validator emas: takror →MongoServerError 11000,Model.init()bilan indeksni kuting.- Model nomidan kolleksiya nomi inglizcha ko'plik (
vazifas) — doim aniq nom bering. strictsukut — noma'lum maydon jim tashlanadi;strict: "throw"—StrictModeError.
Keyingi dars: Mongoose CRUD va update operatorlari — find, findOneAndUpdate va returnDocument: 'after', hamda update'da validatsiya nega ishlamaydi.
Manbalar
- Mongoose 9 hujjati — Schemas: https://mongoosejs.com/docs/guide.html
- Mongoose hujjati — SchemaTypes: https://mongoosejs.com/docs/schematypes.html
- Mongoose hujjati — Validation (unique validator emasligi haqida): https://mongoosejs.com/docs/validation.html
- Mongoose hujjati — Models (kolleksiya nomi): https://mongoosejs.com/docs/models.html
- Mongoose hujjati —
autoIndexva prodakshn: https://mongoosejs.com/docs/guide.html#indexes - Kanon o'lchovi (IlmHamroh, 2026-10-25): Node 24.21.0, mongoose 9.11.2, MongoDB 8.3.13 (Docker). Bazasiz sinovlar va mashq yechimlari — biz ishga tushirdik (mongoose 9.11.2, Node 24.21.0, Windows 11).
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!