IlmHamroh
JavaScript Full-stack/30-qism. NestJS33/65-dars14 daqiqa
Mundarija (24)

Mongoose bilan NestJS: @Schema, @Prop, SchemaFactory va @InjectModel

Qisqacha: @nestjs/mongoose Mongoose sxemasini klass bilan yozishga imkon beradi: @Schema() — klassning o'zi, @Prop({ required: true, maxlength: 100 }) — har maydon. SchemaFactory.createForClass(Vazifa) undan oddiy Mongoose sxemasini yasaydi. MongooseModule.forRootAsync ulanishni, forFeature([{ name, schema }]) modelni ro'yxatga qo'yadi; xizmat uni @InjectModel(Vazifa.name) model: Model<Vazifa> bilan oladi. Hook'lar (pre("save")) va validatsiya 27-qismdagi Mongoose'ning o'zi — Nest faqat DI va dekoratorni qo'shadi.

Bu darsda

  • @Schema / @Prop bilan Mongoose sxemasini klass ko'rinishida yozasiz va SchemaFactory nima qilishini ko'rasiz.
  • MongooseModule.forRootAsync, forFeature va @InjectModel bilan modelni xizmatga ulaysiz.
  • pre("save") hook'ini, returnDocument: "after" va lean() ni Nest ichida ishlatasiz.
  • Validatsiya xatosining haqiqiy matnini o'qiysiz va Mongoose 9 dagi eskirish ogohlantirishini bilasiz.
  • Mongo nega vazifalar-api ga kirmaganini eslaysiz.

Oldin bilishingiz kerak: Mongoose: schema va model, Mongoose CRUD va update operatorlari, Mongoose ilg'or, TypeORM bilan NestJS.

O'tgan darsda TypeORM uchun rasmiy Nest modulini ko'rdik: forRootAsync, forFeature, @InjectRepository. Mongoose moduli xuddi shu qolipda — faqat "repository" o'rnida "model".

1. Nega bu kerak?

27-qismda Mongoose sxemasini oddiy obyekt bilan yozgandik (Mongoose: schema va model):

ts
const VazifaSxemasi = new Schema({
  matn: { type: String, required: true, trim: true, maxlength: 100 },
  bajarildi: { type: Boolean, default: false },
});
type Vazifa = InferSchemaType<typeof VazifaSxemasi>;

Sxema — ish vaqtidagi obyekt, tur — undan chiqarilgan. Nest loyihasida esa hamma narsa klass va dekorator: controller, xizmat, DTO. @nestjs/mongoose sxemani ham shu tilga o'tkazadi — klass yozasiz, sxema undan yasaladi.

Ikkinchi sabab — DI. Model bitta bo'lishi, ulanish ilova bilan birga ochilib-yopilishi va kerakli xizmatga yetishi kerak. Bu — o'tgan ikki darsdagi masala, yechim ham o'sha.

O'xshatish: mebel chizmasi va zavod. @Schema klassi — chizma: qanday detal, qanday o'lcham. SchemaFactory — chizmadan stanok dasturini tayyorlaydi. MongooseModule — zavod: stanokni ishga tushiradi va tayyor mahsulotni (modelni) kerakli sexga beradi.

2. Sxema — klass bilan

2.1 Kanon tajribasidagi sxema

ts
@Schema({
  collection: "vazifalar",
  timestamps: { createdAt: "yaratildi", updatedAt: "yangilandi" },
})
class Vazifa {
  @Prop({ required: true, trim: true, minlength: 1, maxlength: 100 })
  matn!: string;
  @Prop({ default: false }) bajarildi!: boolean;
  @Prop({ type: [String], default: [] }) teglar!: string[];
}
type VazifaHujjat = HydratedDocument<Vazifa>;
const VazifaSxemasi = SchemaFactory.createForClass(Vazifa);

(Kanon tajribasi kodi, telefon uchun bo'lindi.)

  • @Schema({...}) — Mongoose'ning new Schema(…, sozlamalar) dagi ikkinchi argumenti. collection: "vazifalar" — kolleksiya nomini aniq beradi. Usiz Mongoose model nomidan inglizcha ko'plik yasaydi: Vazifa → vazifas. Bu 27-qismda topilgan tuzoq (Mongoose: schema va model).
  • timestamps — yaratilish va o'zgarish vaqtini Mongoose o'zi yozadi; maydon nomlari o'zbekcha.
  • @Prop({...}) — maydon sozlamalari, 27-qismdagi bilan bir xil: required, trim, minlength, maxlength, default.
  • @Prop({ type: [String] }) — massiv. Bu yerda turni aniq yozish shart: TypeScript string[] turi ish vaqtida metama'lumotda faqat Array bo'lib qoladi — ichidagi tur yo'qoladi (Reflector va metadata).
  • HydratedDocument<Vazifa> — "bazadan kelgan, metodlari bor hujjat" turi: Vazifa maydonlari + _id, save(), get().

2.2 SchemaFactory nima yasadi?

Bazasiz tekshirib ko'rdik (biz ishga tushirdik: @nestjs/mongoose 12.0.0, Mongoose 9.11.2). Sxemaning yo'llari va modelning kolleksiya nomi:

text
yo'llar: matn, bajarildi, teglar, _id, yaratildi, yangilandi
kolleksiya: vazifalar

Uchta @Prop maydoniga Mongoose _id va timestamps dagi ikki maydonni qo'shdi. Ya'ni SchemaFactory.createForClass natijasi — oddiy Mongoose sxemasi; 27-qismda o'rgangan hamma narsa (indekslar, virtual maydonlar, hook'lar) unga ham ishlaydi.

Klassdan xizmatgacha yo'l:

flowchart LR
  K["@Schema klass Vazifa"] --> SF["SchemaFactory.createForClass"]
  SF --> S["Mongoose Schema + hook"]
  S --> FF["forFeature: VazifaModel"]
  FF --> IM["@InjectModel(Vazifa.name)"]
  IM --> O["Ombor xizmati"]

Chap yarmi — sxema (bir marta, modul yuklanishida), o'ng yarmi — DI. Hook o'rtada, sxemaga qo'shiladi: forFeature gacha qo'shilmagan hook modelga tushmaydi.

2.3 Hook

Kanon tajribasida saqlashdan oldin teglar matndan olinadi:

ts
// hook: saqlashdan oldin teglar matndan
VazifaSxemasi.pre("save", function () {
  const topilgan = this.matn.match(/#[\p{L}\p{N}_]+/gu) ?? [];
  const teglar = topilgan.map((t) => t.slice(1).toLowerCase());
  this.teglar = [...new Set(teglar)];
});

Bu 25-qismdagi teg qoidasining o'zi: # bilan boshlangan so'z, kichik harf, takrorsiz (Set). Kanonda bir qator edi — o'qish uchun uchga bo'lindi, ma'no o'zgarmagan. function — strelka emas: Mongoose this ni hujjatga bog'laydi (this: to'rt qoida).

Hook sxemaga forFeature dan oldin qo'shiladi. Nest hujjatida yana bir yo'l bor — MongooseModule.forFeatureAsync ichida useFactory da sxemani olib hook qo'shish. U hook'ga boshqa provider kerak bo'lganda qulay (masalan, log yoki config). Biz uni sinamadik.

Tekshirib ko'ring: @Prop() teglar!: string[] deb yozildi (type siz). Nima bo'ladi?

Javob

Nest metama'lumotdan faqat Array ni oladi — ichidagi string yo'qolgan. Mongoose maydonni "aralash qiymatlar massivi" deb tushunadi: tekshiruv va aylantirish ishlamaydi. Massiv va murakkab turlarda type ni doim aniq yozing: @Prop({ type: [String] }).

3. Modul va model

3.1 Ulash

ts
@Module({
  imports: [
    MongooseModule.forRootAsync({
      useFactory: () => ({
        uri: "mongodb://127.0.0.1:27030/tajriba30",
        serverSelectionTimeoutMS: 5000,
      }),
    }),
    MongooseModule.forFeature([
      { name: Vazifa.name, schema: VazifaSxemasi },
    ]),
  ],
  providers: [Ombor],
})
class M {}

Bu TypeORM'dagi qolip: forRootAsync — ulanish (haqiqiy loyihada inject: [ConfigService] bilan), forFeature — model. name: Vazifa.name — modelning nomi ("Vazifa"), u token bo'ladi. serverSelectionTimeoutMS: 5000 — Mongo topilmasa 5 s da xato: ilova ishga tushishda osilib qolmasin.

3.2 @InjectModel

ts
@Injectable()
class Ombor {
  constructor(
    @InjectModel(Vazifa.name) private readonly model: Model<Vazifa>,
  ) {}
  async yarat(matn: string): Promise<VazifaHujjat> {
    return this.model.create({ matn });
  }
  royxat() {
    return this.model.find().sort({ yaratildi: 1 }).lean().exec();
  }
  ozgartir(id: string) {
    return this.model
      .findByIdAndUpdate(
        id, { bajarildi: true }, { returnDocument: "after" },
      )
      .lean()
      .exec();
  }
}

Metodlar — 27-qismdagi Mongoose (Mongoose CRUD):

  • returnDocument: "after" — o'zgargandan keyingi hujjatni qaytarish. Sukut — oldingisi; 27-qismda bu tuzoqni ko'rgandik.
  • lean() — Mongoose hujjati emas, oddiy JS obyekt: tezroq, kam xotira, lekin save() va virtual maydonlarsiz (Mongoose ilg'or).
  • exec() — haqiqiy Promise.

4. Natija

Kanon tajribasi vaqtinchalik Mongo konteynerida yurgizildi (kanon o'lchovi, IlmHamroh, 2026-10, NestJS 12.2.0; ba'zi uzun qatorlar kanon yozuvining o'zida kesilgan):

text
kontekst (Mongo ulanishi bilan): 48 ms
yarat: {"_id":"object","matn":"Non olish #Uy #bozor","teglar":["uy","bozor"],"bajarildi":false,"yaratildi":true}
validatsiya: Vazifa validation failed: matn: Path `matn` (`xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...`, length 101) is longer than the maximum
ozgartir (returnDocument: after): {"_id":"6ae1a7094754e6cbcd9adeac","matn":"Non olish #Uy #bozor","bajarildi":true,"teglar":["uy","bozor"],"yaratildi":"2026-10-28T07:40:57.17
royxat (lean): 1 ta

Qatorma-qator:

  • yarat — kirish " Non olish #Uy #bozor " edi. trim chetdagi bo'shliqlarni olib tashladi. Hook teglarni yig'di: #Uy → uy (kichik harf). _id — ObjectId obyekti ("object"), yaratildi — Date (true).
  • validatsiya — 101 belgili matn rad etildi. Kanon yozuvida xabar kesilgan; to'liq matnni biz bazasiz oldik (pastda).
  • ozgartir — bajarildi: true, returnDocument: "after" tufayli yangi qiymat. _id — 24 belgili hex satr; u har ishga tushirishda boshqa (deterministik emas).
  • royxat (lean) — bitta hujjat: yaroqsiz matnli ikkinchisi saqlanmagan.

4.1 Validatsiya xabari to'liq

Xuddi shu sxema bilan, bazaga ulanmasdan — new Model({...}).validateSync() (biz ishga tushirdik):

text
trim: "Non olish #Uy" | bajarildi: false | xato: yo'q
Vazifa validation failed: matn: Path `matn` (`xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...`, length 101) is longer than the maximum allowed length (100).
Vazifa validation failed: matn: Path `matn` is required.

Tarjima: "Vazifa tekshiruvdan o'tmadi: matn — matn yo'li (… uzunligi 101) ruxsat etilgan eng katta uzunlikdan (100) uzun." Ikkinchisi: "matn yo'li majburiy." Xabar shakli: model nomi → maydon → qoida. Mongoose qiymatni 30 belgidan keyin qisqartiradi (...) — log uzun bo'lib ketmasin.

Shu sinovda Node uch marta ogohlantirdi:

text
(node:…) [MONGOOSE] Warning: Mongoose: `Document.prototype.validateSync()` is deprecated and will be removed in Mongoose 10. Use `Document.prototype.validate()` instead.

Tarjima: "validateSync() eskirgan va Mongoose 10 da olib tashlanadi. O'rniga validate() ishlating." Mongoose 9.11.2 da sinxron tekshiruv eskirgan deb belgilangan — yangi kodda await doc.validate(). Bu kutilmagan topilma: 27-qismda Mongoose 9.11 bilan ishlaganda bu metodni ishlatmagandik.

5. HTTP xatosiga aylantirish

Mongoose validatsiya xatosi — mongoose.Error.ValidationError. U ushlanmasa, Nest uni 500 qiladi: mijoz "server buzildi" deb o'ylaydi, aslida u noto'g'ri ma'lumot yuborgan. Prisma darsidagi yo'l bilan — filtr:

ts
@Catch(mongoose.Error.ValidationError)
class MongooseXatoFiltri implements ExceptionFilter {
  catch(x: mongoose.Error.ValidationError, host: ArgumentsHost) {
    host.switchToHttp().getResponse<Response>().status(422).json({
      status: 422,
      xatolar: Object.values(x.errors).map((e) => e.path),
    });
  }
}

Bu — naqsh: biz uni faqat tip tekshiruvidan o'tkazdik (tsc), so'rov bilan sinamadik. Lekin yaxshiroq yo'l — xatoni bazaga yetkazmaslik: kirish ma'lumotini controller darajasida tekshirish (Zod va Standard Schema NestJS'da). Mongoose validatsiyasi — oxirgi himoya chizig'i, birinchisi emas. 25-qismdagi qoida: tekshiruv chegarada (Validatsiya).

6. Hujumchi nigohi

Mongo'da SQL injection yo'q, lekin uning o'z turi bor — operator injection. 27-qismda ko'rgandik (MongoDB xavfsizligi):

ts
// ❌ mijoz yuborgan obyekt to'g'ridan-to'g'ri filtrga
this.model.findOne({ email: body.email, parol: body.parol });
// body = { "email": "aziz@example.com", "parol": { "$ne": "" } }

parol satr emas, { $ne: "" } obyekt — "bo'sh bo'lmagan har qanday parol". Filtr rost bo'ladi va hujumchi parolsiz kiradi. Himoya ikki qavat: kirishni Zod bilan turi bo'yicha tekshirish (satr kutilgan joyda obyekt — 400) va Mongoose'ning sanitizeFilter: true sozlamasi — u $ bilan boshlangan kalitlarni $eq ga o'raydi. Nest bu himoyani o'zi bermaydi: @Body() — tekshirilmagan qiymat (Controller'lar).

7. Kanon qarori: Mongo loyihaga kirmadi

27-qismda qaror qilingan: vazifalar-api relyatsion — vazifa, teg, izoh, foydalanuvchi o'zaro bog'liq, tranzaksiya va cheklovlar kerak. Mongo — tajriba va boshqa turdagi ma'lumot uchun bilim (MongoDB sxema dizayn naqshlari). 30-qism bu qarorni o'zgartirmaydi. Kanon tajribasi esa ko'rsatdi: Nest + Mongoose juftligi muammosiz — kontekst 48 ms, CRUD, hook va validatsiya 27-qismdagidek.

Mongoose (27) @nestjs/mongoose
Sxema new Schema({...}) @Schema klass + SchemaFactory
Tur InferSchemaType klassning o'zi
Model model("Vazifa", sxema) forFeature + @InjectModel
Ulanish mongoose.connect qo'lda forRootAsync, yopish — modul

7.1 Uch dars — bitta qolip

Prisma, TypeORM va Mongoose darslarini yonma-yon qo'ysak, Nest'da ma'lumot qatlamini ulashning bitta qolipi ko'rinadi. Har ustun bitta savolga javob beradi:

Savol Prisma TypeORM Mongoose
Ulanishni kim yaratadi? PrismaService (o'zimiz) TypeOrmModule.forRootAsync MongooseModule.forRootAsync
Ochish va yopish onModuleInit / onModuleDestroy — o'zimiz modul o'zi modul o'zi
Ma'lumot obyektini ro'yxatga qo'yish kerak emas — klientda hammasi bor forFeature([Entity]) forFeature([{ name, schema }])
Xizmat qanday oladi constructor'da PrismaService @InjectRepository(Entity) @InjectModel(Vazifa.name)
Token klassning o'zi VazifaEntityRepository VazifaModel
Kanon tajribasi ishladi, loyihaga kirmadi ishladi, loyihaga kirmadi ishladi, loyihaga kirmadi

Ikki xulosa. Birinchisi: rasmiy modul bor joyda (@nestjs/typeorm, @nestjs/mongoose) lifecycle'ni yozmaysiz — modul o'zi ochadi va yopadi. Rasmiy modul yo'q joyda (Prisma, Drizzle va Kysely) shu ishni lifecycle hook'lar bilan o'zingiz qilasiz. Ikkinchisi: token nomi qolipga ko'ra yasaladi. Nest can't resolve dependencies xabarida …Repository yoki …Model ni ko'rsangiz — qaysi forFeature yetishmayotganini darhol bilasiz.

8. Ko'p uchraydigan xatolar

Belgi Sabab Davosi
Kolleksiya vazifas collection berilmagan @Schema({ collection: "vazifalar" })
Massivdagi tur tekshirilmaydi @Prop() da type yo'q @Prop({ type: [String] })
Yangilangandan keyin eski qiymat returnDocument sukutda "before" { returnDocument: "after" }
doc.save is not a function lean() — oddiy obyekt lean() siz so'rov
Validatsiya xatosi — 500 filtr yo'q chegarada tekshiruv + filtr
validateSync() is deprecated Mongoose 9 await doc.validate()
Nest can't resolve … VazifaModel forFeature yo'q modulga forFeature([...])

Oxirgi qatordagi nom — @InjectModel tokeni: model nomi + Model. Demo loyihada tekshirdik: getModelToken("Vazifa") → VazifaModel (biz ishga tushirdik). TypeORM'dagi VazifaEntityRepository ga o'xshash qoida.

9. Mashqlar

Mashqlar kurs/mashqlar/30/33-mongoose-nestjs/ da.

1-mashq (oson): dekorator va sozlama

To'ldiring:

  • Klassni sxema deb belgilaydigan dekorator — @
  • Klassdan Mongoose sxemasini yasaydigan metod — SchemaFactory.
  • O'zgargandan keyingi hujjatni qaytarish: returnDocument:
  • Mongoose qaytaradigan oddiy JS obyekt uchun metod —
Yechim
  • Schema, createForClass — klass → sxema.
  • after — sukut before.
  • lean — tez, lekin save() siz.

2-mashq (o'rta): @Prop qoidalarini tekshiruvchi

Brauzerda ishlaydigan tekshir(qoidalar, hujjat) yozing. qoidalar — { maydon: { required, trim, minlength, maxlength, default } }. Funksiya avval default va trim ni qo'llasin, keyin qoidalarni tekshirib, Mongoose uslubidagi xabarlar massivini qaytarsin: Path \matn` is required.vaPath `matn` (length 101) is longer than the maximum allowed length (100).. Xato bo'lmasa — { ok: true, hujjat }. Ishora: String.prototype.trim` (Matnni tozalash).

Yechim
js
const qoidalar = {
  matn: { required: true, trim: true, minlength: 1, maxlength: 100 },
  bajarildi: { default: false },
};

function tekshir(qoidalar, kirish) {
  const hujjat = { ...kirish };
  const xatolar = [];
  for (const [m, q] of Object.entries(qoidalar)) {
    if (hujjat[m] === undefined && "default" in q) {
      hujjat[m] = q.default;
    }
    if (q.trim && typeof hujjat[m] === "string") {
      hujjat[m] = hujjat[m].trim();
    }
    const v = hujjat[m];
    if (q.required && (v === undefined || v === "")) {
      xatolar.push(`Path \`${m}\` is required.`);
    } else if (q.maxlength !== undefined && v.length > q.maxlength) {
      xatolar.push(`Path \`${m}\` (length ${v.length}) is longer ` +
        `than the maximum allowed length (${q.maxlength}).`);
    }
  }
  return xatolar.length > 0
    ? { ok: false, xatolar }
    : { ok: true, hujjat };
}

console.log(tekshir(qoidalar, { matn: "  Non olish #Uy  " }));
console.log(tekshir(qoidalar, { matn: "x".repeat(101) }).xatolar[0]);
console.log(tekshir(qoidalar, { matn: "   " }).xatolar[0]);

Konsolda:

text
{ ok: true, hujjat: { matn: 'Non olish #Uy', bajarildi: false } }
Path `matn` (length 101) is longer than the maximum allowed length (100).
Path `matn` is required.

Uchinchi holatga qarang: " " — bo'shliqlardan iborat. trim dan keyin "" bo'ldi va required ushladi. Tartib muhim: avval tozalash, keyin tekshirish. Haqiqiy Mongoose ham shunday — tajribadagi trim: "Non olish #Uy" qatori buni ko'rsatdi.

3-mashq (qiyin): operator injection'dan himoya

filtrniTozala(filtr) yozing: Mongoose'ning sanitizeFilter g'oyasi. Har kalit qiymati obyekt bo'lsa va uning kaliti $ bilan boshlansa — qiymatni { $eq: qiymat } ga o'rasin (ya'ni operator emas, aynan shu obyektga tenglik). Oddiy qiymatlarga tegmasin. Keyin topish(bazadagilar, filtr) — $eq va $ne ni tushunadigan kichik qidiruv yozing va hujumni tozalashdan oldin va keyin sinang. Ishora: Object.keys(v).some((k) => k.startsWith("$")) (Obyekt bo'ylab yurish).

Yechim
js
function filtrniTozala(filtr) {
  const natija = {};
  for (const [k, v] of Object.entries(filtr)) {
    const operatorli = typeof v === "object" && v !== null &&
      Object.keys(v).some((x) => x.startsWith("$"));
    natija[k] = operatorli ? { $eq: v } : v;
  }
  return natija;
}

function mos(qiymat, shart) {
  if (typeof shart !== "object" || shart === null) {
    return qiymat === shart;
  }
  if ("$eq" in shart) {
    return JSON.stringify(qiymat) === JSON.stringify(shart.$eq);
  }
  if ("$ne" in shart) return qiymat !== shart.$ne;
  return false;
}

const topish = (baza, filtr) => baza.filter((h) =>
  Object.entries(filtr).every(([k, s]) => mos(h[k], s)));

const baza = [{ email: "aziz@example.com", parol: "maxfiy-hash" }];
const hujum = { email: "aziz@example.com", parol: { $ne: "" } };

console.log("tozalanmagan:", topish(baza, hujum).length);
console.log("tozalangan:", topish(baza, filtrniTozala(hujum)).length);
console.log(JSON.stringify(filtrniTozala(hujum)));

Konsolda:

text
tozalanmagan: 1
tozalangan: 0
{"email":"aziz@example.com","parol":{"$eq":{"$ne":""}}}

Tozalanmagan filtr hujjatni topdi — hujumchi kirdi. Tozalangandan keyin parol "aynan { $ne: "" } obyektiga teng" degan shartga aylandi va hech narsa topilmadi. Model haqiqiy Mongo qidiruvidan juda sodda, lekin himoya g'oyasi aynan shu. Bundan ham yaxshisi — bunday obyekt umuman controller'dan o'tmasin: parol uchun z.string() sxemasi uni 400 bilan qaytaradi.

10. Loyiha qadami: o'zgarish yo'q — va nega

vazifalar-api o'zgarmaydi: 27-qismdagi qaror bo'yicha Mongo loyihaga kirmaydi, «Kanon qarori» bo'limida sabablari. Kanon tajribasi Nest bilan ishlashni tasdiqladi — ulanish, CRUD, hook, validatsiya.

Agar Mongo bilan alohida loyiha qilsangiz (masalan, log yoki mahsulot katalogi uchun), shu darsdagi tuzilma tayyor andoza: vazifa.schema.ts (klass + SchemaFactory), modulda forFeature, xizmatda @InjectModel.

11. Real ishda

  • @nestjs/mongoose — Nest + Mongo loyihalarining standarti; *.schema.ts fayllari va @InjectModel ni ko'p uchratasiz.
  • lean() — o'qish so'rovlarida deyarli doim; review'da "nega bu yerda lean yo'q?" savoli tez-tez beriladi.
  • Operator injection — Mongo ishlatadigan API'larda klassik zaiflik; pentest hisobotlarida uchraydi.
  • Intervyu: "Nest'da Mongoose sxemasini qanday yozasiz?", "@Prop({ type: [String] }) nega kerak?", "returnDocument nima?".

Xulosa

  • @Schema + @Prop — sxema klass ko'rinishida; SchemaFactory.createForClass — oddiy Mongoose sxemasi.
  • collection ni aniq bering; massiv va murakkab turlarda type ni aniq yozing.
  • forRootAsync — ulanish, forFeature — model, @InjectModel(Vazifa.name) — Model<Vazifa>.
  • Hook'lar, returnDocument: "after", lean() — 27-qismdagi Mongoose, o'zgarishsiz.
  • Mongoose 9 da validateSync() eskirgan — await validate().
  • Kirishni chegarada tekshiring: Mongoose validatsiyasi va sanitizeFilter — oxirgi himoya.

Keyingi dars: Drizzle va Kysely bilan NestJS — rasmiy moduli yo'q kutubxonani useFactory, Symbol token va onModuleDestroy bilan o'zimiz ulaymiz.

Manbalar

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
Mongoose bilan NestJS: @Schema, @Prop, SchemaFactory va @InjectModel — IlmHamroh