MongoDB Mongoose

导读

警告 在本文中,您将学习如何使用自定义组件从头开始基于 Mongoose 包创建 DatabaseModule。因此,此解决方案包含大量开销,您可以使用现成的、开箱即用的专用 @nestjs/mongoose 包来省略这些开销。要了解更多信息,请参阅 此处

Mongoose 是最流行的 MongoDB 对象建模工具。

入门

要开始使用此库,我们必须安装所有必需的依赖项:

bash
$ npm install --save mongoose

我们需要做的第一步是使用 connect() 函数与我们的数据库建立连接。 connect() 函数返回一个 Promise,因此我们必须创建一个 异步提供程序

ts
database.providers
ts
import * as mongoose from 'mongoose'

export const databaseProviders = [
  {
    provide: 'DATABASE_CONNECTION',
    useFactory: (): Promise<typeof mongoose> =>
      mongoose.connect('mongodb://localhost/nest'),
  },
]
提示

按照最佳实践,我们在带有 *.providers.ts 后缀的分离文件中声明了自定义提供程序。

然后,我们需要导出这些提供程序,使它们可供应用程序的其余部分访问

database.module
ts
import { Module } from '@nestjs/common'
import { databaseProviders } from './database.providers'

@Module({
  providers: [...databaseProviders],
  exports: [...databaseProviders],
})
export class DatabaseModule {}

现在我们可以使用 @Inject() 装饰器注入 Connection 对象。每个依赖于 Connection 异步提供程序的类都将等待,直到 Promise 被解析。

模型注入

使用 Mongoose,所有内容都来自 Schema。让我们定义 CatSchema

schemas/cat.schema
ts
import * as mongoose from 'mongoose'

export const CatSchema = new mongoose.Schema({
  name: String,
  age: Number,
  breed: String,
})

CatsSchema 属于 cats 目录。此目录代表 CatsModule

现在是时候创建一个 Model 提供程序了:

ts
cats.providers
ts
import { Connection } from 'mongoose'
import { CatSchema } from './schemas/cat.schema'

export const catsProviders = [
  {
    provide: 'CAT_MODEL',
    useFactory: (connection: Connection) => connection.model('Cat', CatSchema),
    inject: ['DATABASE_CONNECTION'],
  },
]
警告

在实际应用中,您应该避免使用魔法字符串CAT_MODELDATABASE_CONNECTION 都应保存在单独的 constants.ts 文件中。

现在我们可以使用 @Inject() 装饰器将 CAT_MODEL 注入到 CatsService

ts
cats.service
ts
import { Model } from 'mongoose'
import { Inject, Injectable } from '@nestjs/common'
import { Cat } from './interfaces/cat.interface'
import { CreateCatDto } from './dto/create-cat.dto'

@Injectable()
export class CatsService {
  constructor(
    @Inject('CAT_MODEL')
    private catModel: Model<Cat>,
  ) {}

  async create(createCatDto: CreateCatDto): Promise<Cat> {
    const createdCat = new this.catModel(createCatDto)
    return createdCat.save()
  }

  async findAll(): Promise<Cat[]> {
    return this.catModel.find().exec()
  }
}

在上面的例子中,我们使用了 Cat 接口。此接口扩展了 mongoose 包中的 Document

ts
import { Document } from 'mongoose'

export interface Cat extends Document {
  readonly name: string
  readonly age: number
  readonly breed: string
}

数据库连接是异步的,但 Nest 使这个过程对最终用户完全不可见。CatModel 类正在等待数据库连接,而 CatsService 则被延迟,直到模型准备好使用。当每个类被实例化时,整个应用程序就可以启动。

这是最终的 CatsModule

cats.module
ts
import { Module } from '@nestjs/common'
import { DatabaseModule } from '../database/database.module'
import { CatsController } from './cats.controller'
import { CatsService } from './cats.service'
import { catsProviders } from './cats.providers'

@Module({
  imports: [DatabaseModule],
  controllers: [CatsController],
  providers: [
    CatsService,
    ...catsProviders,
  ],
})
export class CatsModule {}
提示

不要忘记将 CatsModule 导入到根 AppModule

示例

此处 中提供了一个工作示例。