<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                ## Mongo `Nest`支持兩種與 [MongoDB](http://www.mongodb.org/) 數據庫集成的方式。既使用內置的[TypeORM](https://github.com/typeorm/typeorm) 提供的 MongoDB 連接器,或使用最流行的 MongoDB 對象建模工具 [Mongoose](http://mongoosejs.com/)。在本章后續描述中我們使用專用的`@nestjs/mongoose`包。 首先,我們需要安裝所有必需的依賴項: ```bash $ npm install --save @nestjs/mongoose mongoose ``` 安裝過程完成后,我們可以將其 `MongooseModule` 導入到根目錄 `AppModule` 中。 > app.module.ts ```typescript import { Module } from '@nestjs/common'; import { MongooseModule } from '@nestjs/mongoose'; @Module({ imports: [MongooseModule.forRoot('mongodb://localhost/nest')], }) export class AppModule {} ``` 該 `forRoot()` 和 [mongoose](http://mongoosejs.com/) 包中的 `mongoose.connect()` 一樣的參數對象。[參見](https://mongoosejs.com/docs/connections.html)。 ### 模型注入 在`Mongoose`中,一切都源于 [Scheme](http://mongoosejs.com/docs/guide.html),每個 `Schema` 都會映射到 `MongoDB` 的一個集合,并定義集合內文檔的結構。`Schema` 被用來定義模型,而模型負責從底層創建和讀取 `MongoDB` 的文檔。 `Schema` 可以用 `NestJS` 內置的裝飾器來創建,或者也可以自己動手使用 `Mongoose`的常規方式。使用裝飾器來創建 `Schema` 會極大大減少引用并且提高代碼的可讀性。 我們先定義`CatSchema`: > schemas/cat.schema.ts ```typescript import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; import { Document } from 'mongoose'; export type CatDocument = Cat & Document; @Schema() export class Cat extends Document { @Prop() name: string; @Prop() age: number; @Prop() breed: string; } export const CatSchema = SchemaFactory.createForClass(Cat); ``` > 注意你也可以通過使用 `DefinitionsFactory` 類(可以從 `@nestjs/mongoose` 導入)來生成一個原始 `Schema` ,這將允許你根據被提供的元數據手動修改生成的 `Schema` 定義。這對于某些很難用裝飾器體現所有的極端例子非常有用。 `@Schema` 裝飾器標記一個類作為`Schema` 定義,它將我們的 `Cat` 類映射到 `MongoDB` 同名復數的集合 `Cats`,這個裝飾器接受一個可選的 `Schema` 對象。將它想象為那個你通常會傳遞給 `mongoose.Schema` 類的構造函數的第二個參數(例如, `new mongoose.Schema(_, options))`)。 更多可用的 `Schema` 選項可以 [看這里](https://mongoosejs.com/docs/guide.html#options)。 `@Prop` 裝飾器在文檔中定義了一個屬性。舉個例子,在上面的 `Schema` 定義中,我們定義了三個屬性,分別是:`name` ,`age` 和 `breed`。得益于 `TypeScript` 的元數據(還有反射),這些屬性的 [`Schema類型`](https://mongoosejs.com/docs/schematypes.html)會被自動推斷。然而在更復雜的場景下,有些類型例如對象和嵌套數組無法正確推斷類型,所以我們要向下面一樣顯式的指出。 ```typescript @Prop([String]) tags: string[]; ``` 另外的 `@Prop` 裝飾器接受一個可選的參數,通過這個,你可以指示這個屬性是否是必須的,是否需要默認值,或者是標記它作為一個常量,下面是例子: ```typescript @Prop({ required: true }) name: string; ``` 最后的,原始 `Schema` 定義也可以被傳遞給裝飾器。這也非常有用,舉個例子,一個屬性體現為一個嵌套對象而不是一個定義的類。要使用這個,需要從像下面一樣從 `@nestjs/mongoose` 包導入 `raw()`。 ```typescript @Prop(raw({ firstName: { type: String }, lastName: { type: String } })) details: Record<string, any>; ``` 或者,如果你不喜歡使用裝飾器,你可以使用 `mongoose.Schema` 手動定義一個 `Schema`。下面是例子: > schemas/cat.schema.ts ```typescript import * as mongoose from 'mongoose'; export const CatSchema = new mongoose.Schema({ name: String, age: Number, breed: String, }); ``` 該 `cat.schema` 文件在 `cats` 目錄下。這個目錄包含了和 `CatsModule`模塊有關的所有文件。你可以決定在哪里保存`Schema`文件,但我們推薦在他們的**域**中就近創建,即在相應的模塊目錄中。 我們來看看`CatsModule`: > cats.module.ts ```typescript import { Module } from '@nestjs/common'; import { MongooseModule } from '@nestjs/mongoose'; import { CatsController } from './cats.controller'; import { CatsService } from './cats.service'; import { Cat, CatSchema } from './schemas/cat.schema'; @Module({ imports: [MongooseModule.forFeature([{ name: Cat.name, schema: CatSchema }])], controllers: [CatsController], providers: [CatsService], }) export class CatsModule {} ``` `MongooseModule`提供了`forFeature()`方法來配置模塊,包括定義哪些模型應該注冊在當前范圍中。如果你還想在另外的模塊中使用這個模型,將`MongooseModule`添加到`CatsModule`的`exports`部分并在其他模塊中導入`CatsModule`。 注冊`Schema`后,可以使用 `@InjectModel()` 裝飾器將 `Cat` 模型注入到 `CatsService` 中: > cats.service.ts ```typescript import { Model } from 'mongoose'; import { Injectable } from '@nestjs/common'; import { InjectModel } from '@nestjs/mongoose'; import { Cat, CatDocument } from './schemas/cat.schema'; import { CreateCatDto } from './dto/create-cat.dto'; @Injectable() export class CatsService { constructor(@InjectModel('Cat') private catModel: Model<CatDocument>) {} async create(createCatDto: CreateCatDto): Promise<Cat> { const createdCat = new this.catModel(createCatDto); return createdCat.save(); } async findAll(): Promise<Cat[]> { return this.catModel.find().exec(); } } ``` ### 連接 有時你可能需要連接原生的[Mongoose 連接](https://mongoosejs.com/docs/api.html#Connection)對象,你可能在連接對象中想使用某個原生的 API。你可以使用如下的`@InjectConnection()`裝飾器來注入 Mongoose 連接。 ```typescript import { Injectable } from '@nestjs/common'; import { InjectConnection } from '@nestjs/mongoose'; import { Connection } from 'mongoose'; @Injectable() export class CatsService { constructor(@InjectConnection() private connection: Connection) {} } ``` ### 多數據庫 有的項目需要多數據庫連接,可以在這個模塊中實現。要使用多連接,首先要創建連接,在這種情況下,*連接*必須要有名稱。 > app.module.ts ```typescript import { Module } from '@nestjs/common'; import { MongooseModule } from '@nestjs/mongoose'; @Module({ imports: [ MongooseModule.forRoot('mongodb://localhost/test', { connectionName: 'cats', }), MongooseModule.forRoot('mongodb://localhost/users', { connectionName: 'users', }), ], }) export class AppModule {} ``` > 你不能在沒有名稱的情況下使用多連接,也不能對多連接使用同一個名稱,否則會被覆蓋掉。 在設置中,要告訴`MongooseModule.forFeature()`方法應該使用哪個連接。 ```typescript @Module({ imports: [MongooseModule.forFeature([{ name: 'Cat', schema: CatSchema }], 'cats')], }) export class AppModule {} ``` 也可以向一個給定的連接中注入`Connection`。 ```typescript import { Injectable } from '@nestjs/common'; import { InjectConnection } from '@nestjs/mongoose'; import { Connection } from 'mongoose'; @Injectable() export class CatsService { constructor(@InjectConnection('cats') private connection: Connection) {} } ``` ### 鉤子(中間件) 中間件(也被稱作預處理(pre)和后處理(post)鉤子)是在執行異步函數時傳遞控制的函數。中間件是針對`Schema`層級的,在寫插件([源碼](https://mongoosejs.com/docs/middleware.html))時非常有用。在 Mongoose 編譯完模型后使用`pre()`或`post()`不會起作用。要在模型注冊前注冊一個鉤子,可以在使用一個工廠提供者(例如 `useFactory`)是使用`MongooseModule`中的`forFeatureAsync()`方法。使用這一技術,你可以訪問一個 Schema 對象,然后使用`pre()`或`post()`方法來在那個 schema 中注冊一個鉤子。示例如下: ```typescript @Module({ imports: [ MongooseModule.forFeatureAsync([ { name: 'Cat', useFactory: () => { const schema = CatsSchema; schema.pre('save', () => console.log('Hello from pre save')); return schema; }, }, ]), ], }) export class AppModule {} ``` 和其他[工廠提供者](https://docs.nestjs.com/fundamentals/custom-providers#factory-providers-usefactory)一樣,我們的工廠函數是異步的,可以通過`inject`注入依賴。 ```typescript @Module({ imports: [ MongooseModule.forFeatureAsync([ { name: 'Cat', imports: [ConfigModule], useFactory: (configService: ConfigService) => { const schema = CatsSchema; schema.pre('save', () => console.log(`${configService.get<string>('APP_NAME')}: Hello from pre save`)); return schema; }, inject: [ConfigService], }, ]), ], }) export class AppModule {} ``` ### 插件 要向給定的 schema 中注冊[插件](https://mongoosejs.com/docs/plugins.html),可以使用`forFeatureAsync()`方法。 ```typescript @Module({ imports: [ MongooseModule.forFeatureAsync([ { name: 'Cat', useFactory: () => { const schema = CatsSchema; schema.plugin(require('mongoose-autopopulate')); return schema; }, }, ]), ], }) export class AppModule {} ``` 要向所有 schema 中立即注冊一個插件,調用`Connection`對象中的`.plugin()`方法。你可以在所有模型創建前訪問連接。使用`connectionFactory`來實現: > app.module.ts ```typescript import { Module } from '@nestjs/common'; import { MongooseModule } from '@nestjs/mongoose'; @Module({ imports: [ MongooseModule.forRoot('mongodb://localhost/test', { connectionFactory: (connection) => { connection.plugin(require('mongoose-autopopulate')); return connection; }, }), ], }) export class AppModule {} ``` #### 鑒別器[#](#discriminators) [鑒別](https://mongoosejs.com/docs/discriminators.html)器是一種模式繼承機制。它們使您能夠在同一個基礎 MongoDB 集合之上擁有多個具有重疊模式的模型。 假設您想在單個集合中跟蹤不同類型的事件。每個事件都會有一個時間戳。 >event.schema.ts ~~~typescript @Schema({ discriminatorKey: 'kind' }) export class Event { @Prop({ type: String, required: true, enum: [ClickedLinkEvent.name, SignUpEvent.name], }) kind: string; @Prop({ type: Date, required: true }) time: Date; } export const EventSchema = SchemaFactory.createForClass(Event); ~~~ > **提示**:`mongoose` 區分不同判別器模型的方式是`__t`通過默認的“判別器鍵”。`Mongoose` 添加了一個字符串路徑,該路徑調用`__t`到您的模式中,用于跟蹤該文檔是哪個鑒別器的實例。您也可以使用該`discriminatorKey`選項來定義區分路徑。 `SignedUpEvent`和`ClickedLinkEvent`實例將存儲在與通用事件相同的集合中。 現在,讓我們定義`ClickedLinkEvent`類,如下所示: >click-link-event.schema.ts ~~~typescript @Schema() export class ClickedLinkEvent { kind: string; time: Date; @Prop({ type: String, required: true }) url: string; } export const ClickedLinkEventSchema = SchemaFactory.createForClass(ClickedLinkEvent); ~~~ 和`SignUpEvent`類: >sign-up-event.schema.ts ~~~typescript @Schema() export class SignUpEvent { kind: string; time: Date; @Prop({ type: String, required: true }) user: string; } export const SignUpEventSchema = SchemaFactory.createForClass(SignUpEvent); ~~~ 有了這個,使用`discriminators`選項為給定的模式注冊一個鑒別器。它適用于`MongooseModule.forFeature`和`MongooseModule.forFeatureAsync`: >event.module.ts ~~~typescript import { Module } from '@nestjs/common'; import { MongooseModule } from '@nestjs/mongoose'; @Module({ imports: [ MongooseModule.forFeature([ { name: Event.name, schema: EventSchema, discriminators: [ { name: ClickedLinkEvent.name, schema: ClickedLinkEventSchema }, { name: SignUpEvent.name, schema: SignUpEventSchema }, ], }, ]), ] }) export class EventsModule {} ~~~ ### 測試 在單元測試我們的應用程序時,我們通常希望避免任何數據庫連接,使我們的測試套件獨立并盡可能快地執行它們。但是我們的類可能依賴于從連接實例中提取的模型。如何處理這些類呢?解決方案是創建模擬模型。 為了簡化這一過程,`@nestjs/mongoose` 包公開了一個 `getModelToken()` 函數,該函數根據一個 `token` 名稱返回一個準備好的`[注入token](https://docs.nestjs.com/fundamentals/custom-providers#di-fundamentals)`。使用此 `token`,你可以輕松地使用任何標準[自定義提供者](https://docs.nestjs.com/fundamentals/custom-providers)技術,包括 `useClass`、`useValue` 和 `useFactory`。例如: ```typescript @Module({ providers: [ CatsService, { provide: getModelToken('Cat'), useValue: catModel, }, ], }) export class CatsModule {} ``` 在本例中,每當任何使用者使用 `@InjectModel()` 裝飾器注入模型時,都會提供一個硬編碼的 `Model<Cat>` (對象實例)。 ### 異步配置 通常,您可能希望異步傳遞模塊選項,而不是事先傳遞它們。在這種情況下,使用 `forRootAsync()` 方法,`Nest`提供了幾種處理異步數據的方法。 第一種可能的方法是使用工廠函數: ```typescript MongooseModule.forRootAsync({ useFactory: () => ({ uri: 'mongodb://localhost/nest', }), }); ``` 與其他工廠提供程序一樣,我們的工廠函數可以是異步的,并且可以通過注入注入依賴。 ```typescript MongooseModule.forRootAsync({ imports: [ConfigModule], useFactory: async (configService: ConfigService) => ({ uri: configService.getString('MONGODB_URI'), }), inject: [ConfigService], }); ``` 或者,您可以使用類而不是工廠來配置 `MongooseModule`,如下所示: ```typescript MongooseModule.forRootAsync({ useClass: MongooseConfigService, }); ``` 上面的構造在 `MongooseModule`中實例化了 `MongooseConfigService`,使用它來創建所需的 `options` 對象。注意,在本例中,`MongooseConfigService` 必須實現 `MongooseOptionsFactory` 接口,如下所示。 `MongooseModule` 將在提供的類的實例化對象上調用 `createMongooseOptions()` 方法。 ```typescript @Injectable() class MongooseConfigService implements MongooseOptionsFactory { createMongooseOptions(): MongooseModuleOptions { return { uri: 'mongodb://localhost/nest', }; } } ``` 為了防止 `MongooseConfigService` 內部創建 `MongooseModule` 并使用從不同模塊導入的提供程序,您可以使用 `useExisting` 語法。 ```typescript MongooseModule.forRootAsync({ imports: [ConfigModule], useExisting: ConfigService, }); ``` ### 例子 一個可用的示例見[這里](https://github.com/nestjs/nest/tree/master/sample/06-mongoose)。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看