Mongo数据库
Mongo数据库
有两种方法可以处理 MongoDB 数据库。您可以使用提供 MongoDB 支持的 ORM,也可以使用最受欢迎的 MongoDB 对象建模工具 Mongoose 。如果您想使用 ORM,可以按照以下步骤操作。否则,我们将使用专用包。@nestjs/mongoose
首先,我们需要安装所有必需的依赖项:
$ npm install --save @nestjs/mongoose mongoose
安装过程完成后,我们可以将其MongooseModule
导入到根目录中ApplicationModule
。
app.module.ts
JS
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
@Module{
imports: [MongooseModule.forRoot('mongodb://localhost/nest')],
})
export class ApplicationModule {}
该forRoot()
方法接受相同的配置对象作为mongoose.connect()
从猫鼬包。
模型注射
使用Mongoose,一切都来自Schema。让我们来定义CatSchema
:
猫/模式/ cat.schema.ts
JS
import * as mongoose from 'mongoose';
export const CatSchema = new mongoose.Schema{
name: String,
age: Number,
breed: String,
}
在CatsSchema
属于cats
目录。这个目录代表了CatsModule
。这是您决定保留架构文件的决定。从我们的角度来看,在相应的模块目录中,最好的方法是将它们保存在几乎所有的域中
。
我们来看看CatsModule
:
猫/ cats.module.ts
JS
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';
import { CatSchema } from './schemas/cat.schema';
@Module{
imports: [MongooseModule.forFeature([{ name: 'Cat', schema: CatSchema }])],
controllers: [CatsController],
providers: [CatsService],
})
export class CatsModule {}
该模块使用forFeature()
方法来定义哪些模型应在当前范围内注册。多亏了这一点,我们可以注入CatModel
的到CatsService
用的@InjectModel()
装饰:
猫/ cats.service.ts
JS
import { Model } from 'mongoose';
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Cat } from './interfaces/cat.interface';
import { CreateCatDto } from './dto/create-cat.dto';
@Injectable()
export class CatsService {
constructor(@InjectModel('Cat') private readonly catModel: Model<Cat>) {}
async create(createCatDto: CreateCatDto): Promise<Cat> {
const createdCat = new this.catModel(createCatDto
return await createdCat.save(
}
async findAll(): Promise<Cat[]> {
return await this.catModel.find().exec(
}
}
测试
在单元测试我们的应用程序时,我们通常希望避免任何数据库连接,使我们的测试套件独立并尽可能快地执行它们。但是我们的类可能依赖于从连接实例中提取的模型。那是什么?解决方案是创建假模型。为了实现这一点,我们应该设置自定义提供程序。实际上,每个注册的模型都由NameModel
token表示,其中Name
是模型的名称。
该@nestjs/mongoose
包公开了getModelToken()
基于给定模型名称返回准备好的令牌的函数。
@Module{
providers: [
CatsService,
{
provide: getModelToken('Cat'),
useValue: catModel,
},
],
})
export class CatsModule {}
现在硬编码catModel将被用作Model<Cat>。每当任何提供者要求Model<Cat>使用@InjectModel()装饰器时,Nest将使用注册的catModel对象。
异步配置
通常,您可能希望异步传递模块选项,而不是事先传递它们。在这种情况下,使用forRootAsync()
方法,提供了几种处理异步数据的方法。
第一种可能的方法是使用工厂功能:
MongooseModule.forRootAsync{
useFactory: () => {
uri: 'mongodb://localhost/nest',
}),
})
显然,我们的工厂表现得像其他每一个(可能async
并且能够通过注入依赖关系inject
)。
MongooseModule.forRootAsync{
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => {
uri: configService.getString('MONGODB_URI'),
}),
inject: [ConfigService],
})
或者,您可以使用类而不是工厂。
MongooseModule.forRootAsync{
useClass: MongooseConfigService,
})
上面的构造将MongooseConfigService
在内部实例化MongooseModule
,并将利用它来创建选项对象。在MongooseConfigService
必须实现MongooseOptionsFactory
的接口。
@Injectable()
class MongooseConfigService implements MongooseOptionsFactory {
createMongooseOptions(): MongooseModuleOptions {
return {
uri: 'mongodb://localhost/nest',
};
}
}
为了防止MongooseConfigService
内部创建MongooseModule
并使用从不同模块导入的提供程序,您可以使用useExisting
语法。
MongooseModule.forRootAsync{
imports: [ConfigModule],
useExisting: ConfigService,
})
它的作用useClass
与一个关键区别相同 - MongooseModule
将查找导入的模块以重新使用已创建的ConfigService
,而不是单独实例化它。