Mongo
Nest MongoDB bazasi bilan integratsiya qilishning ikki usulini qo'llab-quvvatlaydi. Siz bu yerda tasvirlangan MongoDB uchun connectorga ega ichki TypeORM modulidan foydalanishingiz
Nest MongoDB bazasi bilan integratsiya qilishning ikki usulini qo'llab-quvvatlaydi. Siz bu yerda tasvirlangan MongoDB uchun connectorga ega ichki TypeORM modulidan foydalanishingiz yoki MongoDB uchun eng mashhur obyekt modellashtirish vositasi bo'lgan Mongoose ni ishlatishingiz mumkin. Bu bobda biz ikkinchi usulni, ya'ni @nestjs/mongoose paketidan foydalanishni ko'rib chiqamiz.
Kerakli bog'liqliklarni o'rnatishdan boshlang:
1$ npm i @nestjs/mongoose mongooseO'rnatish jarayoni tugagach, MongooseModule ni root AppModule ga import qilamiz.
1import { Module } from '@nestjs/common';
2import { MongooseModule } from '@nestjs/mongoose';
3
4@Module({
5 imports: [MongooseModule.forRoot('mongodb://localhost/nest')],
6})
7export class AppModule {}forRoot() metodi Mongoose paketidagi mongoose.connect() bilan bir xil konfiguratsiya obyektini qabul qiladi, bu yerda tasvirlangan.
Modelni injeksiya qilish
Mongoose da hamma narsa Schema dan kelib chiqadi. Har bir schema MongoDB kolleksiyasiga mos keladi va shu kolleksiyadagi hujjatlarning shaklini belgilaydi. Schemas Model larni ta'riflashda ishlatiladi. Modellar MongoDB bazasidan hujjatlarni yaratish va o'qish uchun javob beradi.
Schemalari NestJS dekoratorlari yordamida yoki Mongoose ning o'zi bilan qo'lda yaratish mumkin. Dekoratorlar orqali schema yaratish boilerplate ni sezilarli kamaytiradi va kod o'qilishini yaxshilaydi.
CatSchema ni aniqlaymiz:
1import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
2import { HydratedDocument } from 'mongoose';
3
4export type CatDocument = HydratedDocument<Cat>;
5
6@Schema()
7export class Cat {
8 @Prop()
9 name: string;
10
11 @Prop()
12 age: number;
13
14 @Prop()
15 breed: string;
16}
17
18export const CatSchema = SchemaFactory.createForClass(Cat);Eslatma: DefinitionsFactory klassi (nestjs/mongoose dan) yordamida xom schema ta'rifini ham generatsiya qilishingiz mumkin. Bu siz bergan metadata asosida yaratilgan schema ta'rifini qo'lda o'zgartirishga imkon beradi. Bu, ba'zi chekka holatlarda hamma narsani dekoratorlar bilan ifodalash qiyin bo'lganda foydali.
@Schema() dekoratori klassni schema ta'rifi sifatida belgilaydi. U bizning Cat klassimizni xuddi shu nomdagi, lekin oxiriga qo'shimcha "s" qo'shilgan MongoDB kolleksiyasiga moslaydi, shuning uchun yakuniy mongo kolleksiya nomi cats bo'ladi. Bu dekorator bitta ixtiyoriy argument qabul qiladi, u schema options obyektidir. Buni mongoose.Schema klassi konstruktorining ikkinchi argumenti sifatida odatda beriladigan obyekt deb o'ylang (masalan, new mongoose.Schema(_, options)). Mavjud schema opsiyalari haqida ko'proq ma'lumot olish uchun shu bobga qarang.
@Prop() dekoratori hujjatdagi xossani belgilaydi. Masalan, yuqoridagi schema ta'rifida biz uchta xossani belgiladik: name, age, va breed. Bu xossalar uchun schema types TypeScript metadata (va reflection) imkoniyatlari orqali avtomatik aniqlanadi. Biroq, turlarni yashirin aniqlab bo'lmaydigan murakkab holatlarda (masalan, massivlar yoki ichma-ich obyekt tuzilmalari), turlarni aniq ko'rsatish kerak, quyidagicha:
1@Prop([String])
2tags: string[];Muqobil ravishda, @Prop() dekoratori options obyektini ham qabul qiladi (mavjud opsiyalar haqida o'qing). Bu orqali xossa majburiyligini ko'rsatish, default qiymat berish yoki uni immutable qilish mumkin. Masalan:
1@Prop({ required: true })
2name: string;Agar boshqa modelga bog'liqlikni keyinroq populate qilish uchun ko'rsatmoqchi bo'lsangiz, @Prop() dekoratoridan foydalanishingiz mumkin. Masalan, agar Cat da Owner bo'lsa va u owners nomli boshqa kolleksiyada saqlansa, xossada type va ref bo'lishi kerak. Masalan:
1import * as mongoose from 'mongoose';
2import { Owner } from '../owners/schemas/owner.schema';
3
4// inside the class definition
5@Prop({ type: mongoose.Schema.Types.ObjectId, ref: 'Owner' })
6owner: Owner;Agar bir nechta owner bo'lsa, xossa konfiguratsiyasi quyidagicha bo'ladi:
1@Prop({ type: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Owner' }] })
2owners: Owner[];Agar boshqa kolleksiyaga bo'lgan reference ni doim ham populate qilmoqchi bo'lmasangiz, type sifatida mongoose.Types.ObjectId dan foydalanishni ko'rib chiqing:
1@Prop({ type: { type: mongoose.Schema.Types.ObjectId, ref: 'Owner' } })
2// This ensures the field is not confused with a populated reference
3owner: mongoose.Types.ObjectId;Shundan so'ng, keyinroq uni tanlab populate qilish kerak bo'lganda, to'g'ri type ko'rsatadigan repository funksiyasidan foydalanishingiz mumkin:
1import { Owner } from './schemas/owner.schema';
2
3// e.g. inside a service or repository
4async findAllPopulated() {
5 return this.catModel.find().populate<{ owner: Owner }>("owner");
6}Agar populate qilinadigan foreign hujjat bo'lmasa, type Owner | null bo'lishi mumkin, sizning Mongoose konfiguratsiyangiz ga qarab. Muqobil ravishda, xato qaytarishi ham mumkin, bu holda type Owner bo'ladi.
Nihoyat, dekoratorga xom schema ta'rifini ham berish mumkin. Bu, masalan, xossa class sifatida aniqlanmagan ichma-ich obyektni ifodalaganda foydali. Buning uchun @nestjs/mongoose paketidagi raw() funksiyasidan foydalaning:
1@Prop(raw({
2 firstName: { type: String },
3 lastName: { type: String }
4}))
5details: Record<string, any>;Agar dekoratorlardan foydalanmaslikni afzal ko'rsangiz, schemani qo'lda aniqlashingiz mumkin. Masalan:
1export const CatSchema = new mongoose.Schema({
2 name: String,
3 age: Number,
4 breed: String,
5});cat.schema fayli cats papkasi ichida joylashgan bo'ladi; shu yerda CatsModule ham aniqlanadi. Schema fayllarini xohlagan joyingizda saqlashingiz mumkin, ammo ularni tegishli domen obyektlari yonida, mos modul papkasida saqlashni tavsiya qilamiz.
Endi CatsModule ni ko'rib chiqamiz:
1import { Module } from '@nestjs/common';
2import { MongooseModule } from '@nestjs/mongoose';
3import { CatsController } from './cats.controller';
4import { CatsService } from './cats.service';
5import { Cat, CatSchema } from './schemas/cat.schema';
6
7@Module({
8 imports: [MongooseModule.forFeature([{ name: Cat.name, schema: CatSchema }])],
9 controllers: [CatsController],
10 providers: [CatsService],
11})
12export class CatsModule {}MongooseModule modulni sozlash uchun forFeature() metodini taqdim etadi, shu jumladan joriy scope da qaysi modellarni ro'yxatdan o'tkazish kerakligini ham belgilaydi. Agar modellardan boshqa modulda ham foydalanmoqchi bo'lsangiz, CatsModule ning exports bo'limiga MongooseModule ni qo'shing va boshqa modulda CatsModule ni import qiling.
Schema ro'yxatdan o'tkazilgach, @InjectModel() dekoratori yordamida CatsService ga Cat modelini inject qilishingiz mumkin:
1import { Model } from 'mongoose';
2import { Injectable } from '@nestjs/common';
3import { InjectModel } from '@nestjs/mongoose';
4import { Cat } from './schemas/cat.schema';
5import { CreateCatDto } from './dto/create-cat.dto';
6
7@Injectable()
8export class CatsService {
9 constructor(@InjectModel(Cat.name) private catModel: Model<Cat>) {}
10
11 async create(createCatDto: CreateCatDto): Promise<Cat> {
12 const createdCat = new this.catModel(createCatDto);
13 return createdCat.save();
14 }
15
16 async findAll(): Promise<Cat[]> {
17 return this.catModel.find().exec();
18 }
19}Ulanish
Ba'zan native Mongoose Connection obyektiga kirish kerak bo'lishi mumkin. Masalan, ulanish obyektida native API chaqiruvlarini bajarishni xohlashingiz mumkin. @InjectConnection() dekoratori yordamida Mongoose Connection ni quyidagicha inject qilishingiz mumkin:
1import { Injectable } from '@nestjs/common';
2import { InjectConnection } from '@nestjs/mongoose';
3import { Connection } from 'mongoose';
4
5@Injectable()
6export class CatsService {
7 constructor(@InjectConnection() private connection: Connection) {}
8}Sessiyalar
Mongoose bilan sessiyani boshlash uchun mongoose.startSession() ni to'g'ridan-to'g'ri chaqirish o'rniga @InjectConnection orqali ma'lumotlar bazasi ulanishini inject qilish tavsiya etiladi. Bu yondashuv NestJS dependency injection tizimi bilan yaxshiroq integratsiya qiladi va ulanishni to'g'ri boshqarishni ta'minlaydi.
Quyida sessiyani qanday boshlash misoli keltirilgan:
1import { InjectConnection } from '@nestjs/mongoose';
2import { Connection } from 'mongoose';
3
4@Injectable()
5export class CatsService {
6 constructor(@InjectConnection() private readonly connection: Connection) {}
7
8 async startTransaction() {
9 const session = await this.connection.startSession();
10 session.startTransaction();
11 // Your transaction logic here
12 }
13}Bu misolda @InjectConnection() dekoratori Mongoose ulanishini servicega inject qilish uchun ishlatiladi. Ulanish inject qilingach, connection.startSession() yordamida yangi sessiyani boshlashingiz mumkin. Bu sessiya bir nechta so'rovlar bo'ylab atomik operatsiyalarni boshqarish uchun ishlatiladi. Sessiya boshlanganidan keyin, mantiqingizga qarab tranzaksiyani commit yoki abort qilishni unutmang.
Bir nechta ma'lumotlar bazasi
Ba'zi loyihalar bir nechta ma'lumotlar bazasi ulanishini talab qiladi. Buni ham ushbu modul orqali amalga oshirish mumkin. Bir nechta ulanish bilan ishlash uchun avval ulanishlarni yarating. Bu holatda ulanishlarni nomlash majburiy bo'ladi.
1import { Module } from '@nestjs/common';
2import { MongooseModule } from '@nestjs/mongoose';
3
4@Module({
5 imports: [
6 MongooseModule.forRoot('mongodb://localhost/test', {
7 connectionName: 'cats',
8 }),
9 MongooseModule.forRoot('mongodb://localhost/users', {
10 connectionName: 'users',
11 }),
12 ],
13})
14export class AppModule {}Eslatma: nomi bo'lmagan yoki bir xil nomdagi bir nechta ulanishlarga ega bo'lmasligingiz kerak, aks holda ular bir-birini bosib ketadi.
Bu sozlama bilan MongooseModule.forFeature() funksiyasiga qaysi ulanishdan foydalanilishi kerakligini aytish kerak.
1@Module({
2 imports: [
3 MongooseModule.forFeature([{ name: Cat.name, schema: CatSchema }], 'cats'),
4 ],
5})
6export class CatsModule {}Berilgan ulanish uchun Connection ni ham inject qilishingiz mumkin:
1import { Injectable } from '@nestjs/common';
2import { InjectConnection } from '@nestjs/mongoose';
3import { Connection } from 'mongoose';
4
5@Injectable()
6export class CatsService {
7 constructor(@InjectConnection('cats') private connection: Connection) {}
8}Berilgan Connection ni custom providerga (masalan, factory provider) inject qilish uchun getConnectionToken() funksiyasidan foydalaning va ulanish nomini argument sifatida bering.
1{
2 provide: CatsService,
3 useFactory: (catsConnection: Connection) => {
4 return new CatsService(catsConnection);
5 },
6 inject: [getConnectionToken('cats')],
7}Agar nomlangan bazadan faqat modelni inject qilmoqchi bo'lsangiz, @InjectModel() dekoratoriga ikkinchi parametr sifatida ulanish nomini berishingiz mumkin.
1@Injectable()
2export class CatsService {
3 constructor(@InjectModel(Cat.name, 'cats') private catModel: Model<Cat>) {}
4}Xuklar (middleware)
Middleware (pre va post hooklar ham deyiladi) - bu asinxron funksiyalar bajarilishi davomida boshqaruvni oladigan funksiyalar. Middleware schema darajasida aniqlanadi va plaginlar yozish uchun foydali (manba). Mongoose da model kompilyatsiya qilingandan keyin pre() yoki post() ni chaqirish ishlamaydi. Hookni model ro'yxatdan o'tkazilishidan oldin ro'yxatdan o'tkazish uchun MongooseModule ning forFeatureAsync() metodidan factory provider (ya'ni, useFactory) bilan birga foydalaning. Bu usul orqali schema obyektiga kirib, pre() yoki post() metodlari yordamida hookni ro'yxatdan o'tkazishingiz mumkin. Quyidagi misolga qarang:
1@Module({
2 imports: [
3 MongooseModule.forFeatureAsync([
4 {
5 name: Cat.name,
6 useFactory: () => {
7 const schema = CatsSchema;
8 schema.pre('save', function () {
9 console.log('Hello from pre save');
10 });
11 return schema;
12 },
13 },
14 ]),
15 ],
16})
17export class AppModule {}Boshqa factory providerlar kabi, factory funksiyamiz async bo'lishi va inject orqali bog'liqliklarni qabul qilishi mumkin.
1@Module({
2 imports: [
3 MongooseModule.forFeatureAsync([
4 {
5 name: Cat.name,
6 imports: [ConfigModule],
7 useFactory: (configService: ConfigService) => {
8 const schema = CatsSchema;
9 schema.pre('save', function() {
10 console.log(
11 `${configService.get('APP_NAME')}: Hello from pre save`,
12 );
13 });
14 return schema;
15 },
16 inject: [ConfigService],
17 },
18 ]),
19 ],
20})
21export class AppModule {}Plaginlar
Berilgan schema uchun plugin ro'yxatdan o'tkazish uchun forFeatureAsync() metodidan foydalaning.
1@Module({
2 imports: [
3 MongooseModule.forFeatureAsync([
4 {
5 name: Cat.name,
6 useFactory: () => {
7 const schema = CatsSchema;
8 schema.plugin(require('mongoose-autopopulate'));
9 return schema;
10 },
11 },
12 ]),
13 ],
14})
15export class AppModule {}Barcha schemalar uchun bir vaqtning o'zida plagin ro'yxatdan o'tkazish uchun Connection obyektining .plugin() metodini chaqiring. Modellar yaratilishidan oldin ulanishga kirishingiz kerak; buni connectionFactory orqali bajaring:
1import { Module } from '@nestjs/common';
2import { MongooseModule } from '@nestjs/mongoose';
3
4@Module({
5 imports: [
6 MongooseModule.forRoot('mongodb://localhost/test', {
7 connectionFactory: (connection) => {
8 connection.plugin(require('mongoose-autopopulate'));
9 return connection;
10 }
11 }),
12 ],
13})
14export class AppModule {}Diskriminatorlar
Discriminators - bu schema meros olish mexanizmi. Ular bir xil MongoDB kolleksiyasi ustida, qisman bir xil schemalarga ega bir nechta modelga ega bo'lishingizga imkon beradi.
Faraz qilaylik, siz bitta kolleksiyada turli turdagi hodisalarni kuzatmoqchisiz. Har bir hodisada vaqt tamg'asi bo'ladi.
1@Schema({ discriminatorKey: 'kind' })
2export class Event {
3 @Prop({
4 type: String,
5 required: true,
6 enum: [ClickedLinkEvent.name, SignUpEvent.name],
7 })
8 kind: string;
9
10 @Prop({ type: Date, required: true })
11 time: Date;
12}
13
14export const EventSchema = SchemaFactory.createForClass(Event);Mongoose turli discriminator modellari o'rtasidagi farqni "discriminator key" orqali aniqlaydi, u default holatda __t bo'ladi. Mongoose schemalaringizga __t nomli String path qo'shadi va u orqali hujjat qaysi discriminator instansiyasi ekanini kuzatadi.
discriminatorKey opsiyasi orqali discriminator yo'lini aniqlashingiz ham mumkin.
SignedUpEvent va ClickedLinkEvent instansiyalari umumiy hodisalar bilan bir xil kolleksiyada saqlanadi.
Endi ClickedLinkEvent klassini quyidagicha aniqlaymiz:
1@Schema()
2export class ClickedLinkEvent {
3 kind: string;
4 time: Date;
5
6 @Prop({ type: String, required: true })
7 url: string;
8}
9
10export const ClickedLinkEventSchema = SchemaFactory.createForClass(ClickedLinkEvent);Va SignUpEvent klassi:
1@Schema()
2export class SignUpEvent {
3 kind: string;
4 time: Date;
5
6 @Prop({ type: String, required: true })
7 user: string;
8}
9
10export const SignUpEventSchema = SchemaFactory.createForClass(SignUpEvent);Shu bilan, berilgan schema uchun discriminator ro'yxatdan o'tkazish uchun discriminators opsiyasidan foydalaning. U MongooseModule.forFeature va MongooseModule.forFeatureAsync ikkalasida ham ishlaydi:
1import { Module } from '@nestjs/common';
2import { MongooseModule } from '@nestjs/mongoose';
3
4@Module({
5 imports: [
6 MongooseModule.forFeature([
7 {
8 name: Event.name,
9 schema: EventSchema,
10 discriminators: [
11 { name: ClickedLinkEvent.name, schema: ClickedLinkEventSchema },
12 { name: SignUpEvent.name, schema: SignUpEventSchema },
13 ],
14 },
15 ]),
16 ]
17})
18export class EventsModule {}Testlash
Ilovani unit testlashda, odatda, hech qanday ma'lumotlar bazasi ulanishidan qochishni xohlaymiz, bu test to'plamlarini o'rnatishni soddalashtiradi va tezlashtiradi. Ammo klasslarimiz ulanish instansiyasidan olinadigan modellarga bog'liq bo'lishi mumkin. Bu klasslarni qanday hal qilamiz? Yechim - mock modellari yaratish.
Buni osonlashtirish uchun @nestjs/mongoose paketi token nomiga asoslangan tayyor injection token qaytaradigan getModelToken() funksiyasini taqdim etadi. Bu token yordamida useClass, useValue va useFactory kabi standart custom provider usullaridan foydalanib osonlik bilan mock implementatsiya berishingiz mumkin. Masalan:
1@Module({
2 providers: [
3 CatsService,
4 {
5 provide: getModelToken(Cat.name),
6 useValue: catModel,
7 },
8 ],
9})
10export class CatsModule {}Bu misolda, qattiq kodlangan catModel (obyekt instansiyasi) har safar @InjectModel() dekoratori orqali Model<Cat> inject qiladigan consumer bo'lsa taqdim etiladi.
Async sozlash
Modul opsiyalarini statik emas, asinxron tarzda uzatishingiz kerak bo'lganda forRootAsync() metodidan foydalaning. Aksariyat dinamik modullar kabi, Nest asinxron konfiguratsiya bilan ishlash uchun bir nechta usullarni taqdim etadi.
Usullardan biri - factory funksiyasidan foydalanish:
1MongooseModule.forRootAsync({
2 useFactory: () => ({
3 uri: 'mongodb://localhost/nest',
4 }),
5});Boshqa factory providerlar kabi, factory funksiyamiz async bo'lishi va inject orqali bog'liqliklarni qabul qilishi mumkin.
1MongooseModule.forRootAsync({
2 imports: [ConfigModule],
3 useFactory: async (configService: ConfigService) => ({
4 uri: configService.get<string>('MONGODB_URI'),
5 }),
6 inject: [ConfigService],
7});Muqobil ravishda, quyida ko'rsatilganidek, MongooseModule ni factory o'rniga klass yordamida sozlashingiz mumkin:
1MongooseModule.forRootAsync({
2 useClass: MongooseConfigService,
3});Yuqoridagi konstruktsiya MongooseConfigService ni MongooseModule ichida yaratadi va undan kerakli opsiyalar obyektini yaratish uchun foydalanadi. E'tibor bering, bu misolda MongooseConfigService MongooseOptionsFactory interfeysini implementatsiya qilishi kerak, bu quyida ko'rsatilgan. MongooseModule taqdim etilgan klass obyektining createMongooseOptions() metodini chaqiradi.
1@Injectable()
2export class MongooseConfigService implements MongooseOptionsFactory {
3 createMongooseOptions(): MongooseModuleOptions {
4 return {
5 uri: 'mongodb://localhost/nest',
6 };
7 }
8}Agar MongooseModule ichida private nusxa yaratmasdan mavjud opsiyalar providerni qayta ishlatmoqchi bo'lsangiz, useExisting sintaksisidan foydalaning.
1MongooseModule.forRootAsync({
2 imports: [ConfigModule],
3 useExisting: ConfigService,
4});Ulanish hodisalari
Mongoose ulanish hodisalari ni onConnectionCreate konfiguratsiya opsiyasi yordamida tinglashingiz mumkin. Bu ulanish o'rnatilganda custom mantiqni ishga tushirishga imkon beradi. Masalan, quyida ko'rsatilgandek connected, open, disconnected, reconnected, va disconnecting hodisalari uchun listenerlar ro'yxatdan o'tkazishingiz mumkin:
1MongooseModule.forRoot('mongodb://localhost/test', {
2 onConnectionCreate: (connection: Connection) => {
3 connection.on('connected', () => console.log('connected'));
4 connection.on('open', () => console.log('open'));
5 connection.on('disconnected', () => console.log('disconnected'));
6 connection.on('reconnected', () => console.log('reconnected'));
7 connection.on('disconnecting', () => console.log('disconnecting'));
8
9 return connection;
10 },
11}),Bu kod parchasida biz mongodb://localhost/test manzilidagi MongoDB bazasiga ulanishni o'rnatmoqdamiz. onConnectionCreate opsiyasi ulanish holatini kuzatish uchun aniq hodisa listenerlarini sozlash imkonini beradi:
connected: ulanish muvaffaqiyatli o'rnatilganda ishga tushadi.open: ulanish to'liq ochilib, operatsiyalar uchun tayyor bo'lganda chaqiriladi.disconnected: ulanish uzilganda chaqiriladi.reconnected: uzilishdan keyin ulanish qayta o'rnatilganda ishga tushadi.disconnecting: ulanish yopilish jarayonida bo'lganda sodir bo'ladi.
Shuningdek, onConnectionCreate xossasini MongooseModule.forRootAsync() bilan yaratilgan asinxron konfiguratsiyalarga ham qo'shishingiz mumkin:
1MongooseModule.forRootAsync({
2 useFactory: () => ({
3 uri: 'mongodb://localhost/test',
4 onConnectionCreate: (connection: Connection) => {
5 // Register event listeners here
6 return connection;
7 },
8 }),
9}),Bu ulanish hodisalarini boshqarish uchun moslashuvchan usul bo'lib, ulanish holatidagi o'zgarishlarni samarali tarzda qayta ishlashga yordam beradi.
Subdokumentlar
Parent hujjat ichida subdokumentlarni joylash uchun schemalaringizni quyidagicha aniqlashingiz mumkin:
1@Schema()
2export class Name {
3 @Prop()
4 firstName: string;
5
6 @Prop()
7 lastName: string;
8}
9
10export const NameSchema = SchemaFactory.createForClass(Name);So'ng subdokumentni parent schema ichida ko'rsating:
1@Schema()
2export class Person {
3 @Prop(NameSchema)
4 name: Name;
5}
6
7export const PersonSchema = SchemaFactory.createForClass(Person);
8
9export type PersonDocumentOverride = {
10 name: Types.Subdocument<Types.ObjectId> & Name;
11};
12
13export type PersonDocument = HydratedDocument<Person, PersonDocumentOverride>;Agar bir nechta subdokumentni kiritmoqchi bo'lsangiz, subdokumentlar massividan foydalanishingiz mumkin. Xossa tipini mos ravishda override qilish muhim:
1@Schema()
2export class Person {
3 @Prop([NameSchema])
4 name: Name[];
5}
6
7export const PersonSchema = SchemaFactory.createForClass(Person);
8
9export type PersonDocumentOverride = {
10 name: Types.DocumentArray<Name>;
11};
12
13export type PersonDocument = HydratedDocument<Person, PersonDocumentOverride>;Virtuals
Mongoose da virtual - bu hujjatda mavjud, lekin MongoDB ga saqlanmaydigan xossa. U bazada saqlanmaydi, lekin unga murojaat qilganda dinamik hisoblanadi. Virtuals odatda hosila yoki hisoblangan qiymatlar uchun ishlatiladi, masalan maydonlarni birlashtirish (masalan, firstName va lastName ni qo'shib fullName xossasini yaratish), yoki hujjatdagi mavjud ma'lumotlarga tayanuvchi xossalarni yaratish uchun.
1class Person {
2 @Prop()
3 firstName: string;
4
5 @Prop()
6 lastName: string;
7
8 @Virtual({
9 get: function (this: Person) {
10 return `${this.firstName} ${this.lastName}`;
11 },
12 })
13 fullName: string;
14}@Virtual() dekoratori @nestjs/mongoose paketidan import qilinadi.
Bu misolda fullName virtuali firstName va lastName dan hosil qilinadi. U chaqirilganda oddiy xossadek ishlaydi, ammo MongoDB hujjatiga hech qachon saqlanmaydi.:
Misol
Ishlaydigan misol bu yerda mavjud.