在现代的Web应用程序开发中,无论是在数据存储、检索、还是数据流转的各个环节,数据库都扮演着极其重要的角色。MongoDB是一个基于分布式文件存储的开源数据库系统,以其高性能、高可用性和易扩展性著称。
作为JavaScript社区最受欢迎的后端框架之一,NestJS 提供了优雅的解决方案来与各种数据库进行交互,其中就包括了对MongoDB的支持。
本教程将通过一个简单而通俗的实例,带你在NestJS中集成MongoDB。我们将创建一个简易的用户管理系统,实现用户的增删改查操作。
在开始之前,请确保你的开发环境中已经安装了以下软件:
npm i -g @nestjs/cli
安装)准备就绪后,我们可以开始动手编写代码了。
使用 Nest CLI 创建一个新项目:
nest new nest-mongodb-example
进入项目目录:
cd nest-mongodb-example
在NestJS中操作MongoDB,我们将使用 @nestjs/mongoose
模块,同时也需要安装mongoose:
npm install @nestjs/mongoose mongoose
我们需要配置NestJS应用来连接到MongoDB数据库。在 src
目录下创建一个名为 configs
的文件夹,并在其中创建 mongodb.config.ts
文件:
// src/configs/mongodb.config.ts
export default {
uri: 'mongodb://localhost/nest-mongodb-example',
};
在 app.module.ts
中导入上述配置并初始化:
// src/app.module.ts
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import mongodbConfig from './configs/mongodb.config';
@Module({
imports: [
MongooseModule.forRoot(mongodbConfig.uri),
// ...其他模块
],
controllers: [],
providers: [],
})
export class AppModule {}
在 MongoDB 中, 我们使用 Schema 定义数据的结构。NestJS配合Mongoose可以让我们方便的操作它。
在 src
目录下创建一个 users
文件夹用来组织用户相关的文件。在其中创建 user.schema.ts
用来定义用户数据模型:
// src/users/user.schema.ts
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { Document } from 'mongoose';
export type UserDocument = User & Document;
@Schema()
export class User {
@Prop({ required: true })
username: string;
@Prop()
email: string;
@Prop()
age: number;
}
export const UserSchema = SchemaFactory.createForClass(User);
然后创建一个对应的服务模块来提供用户的业务逻辑:
nest g module users
nest g service users
这将会自动生成 users.module.ts
和 users.service.ts
文件。
现在,我们将 User
模型和 UserSchema
导入到 UsersModule
中:
// src/users/users.module.ts
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { User, UserSchema } from './user.schema';
import { UsersService } from './users.service';
@Module({
imports: [
MongooseModule.forFeature([{ name: User.name, schema: UserSchema }])
],
providers: [UsersService]
})
export class UsersModule {}
现在,我们的 UsersService
中可以通过依赖注入方式访问 User
模型了。在 users.service.ts
文件中,我们可以实现一些基本的数据库操作:
// src/users/users.service.ts
import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { User, UserDocument } from './user.schema';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';
@Injectable()
export class UsersService {
constructor(@InjectModel(User.name) private userModel: Model<UserDocument>) {}
async create(createUserDto: CreateUserDto): Promise<User> {
const createdUser = new this.userModel(createUserDto);
return createdUser.save();
}
async findAll(): Promise<User[]> {
return this.userModel.find().exec();
}
async findOne(id: string): Promise<User> {
const user = this.userModel.findById(id).exec();
if (!user) {
throw new NotFoundException(`User with ID ${id} not found`);
}
return user;
}
async update(id: string, updateUserDto: UpdateUserDto): Promise<User> {
const updatedUser = await this.userModel.findByIdAndUpdate(id, updateUserDto, { new: true }).exec();
if (!updatedUser) {
throw new NotFoundException(`User with ID ${id} not found`);
}
return updatedUser;
}
async delete(id: string): Promise<User> {
const deletedUser = await this.userModel.findByIdAndRemove(id).exec();
if (!deletedUser) {
throw new NotFoundException(`User with ID ${id} not found`);
}
return deletedUser;
}
}
为了完成我们的CURD操作,我们还需要实现相应的 UsersController
来处理HTTP请求。
此时我们同样应该创建DTO(Data Transfer Object)用来安全的传输数据。
首先,创建 create-user.dto.ts
:
// src/users/dto/create-user.dto.ts
export class CreateUserDto {
readonly username: string;
readonly email?: string;
readonly age?: number;
}
// src/users/dto/update-user.dto.ts
import { PartialType } from '@nestjs/mapped-types';
import { CreateUserDto } from './create-user.dto';
export class UpdateUserDto extends PartialType(CreateUserDto) {}
然后创建 UsersController
:
nest g controller users
在 users.controller.ts
中实现API的接口:
// src/users/users.controller.ts
import { Controller, Get, Post, Body, Put, Param, Delete } from '@nestjs/common';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';
import { UsersService } from './users.service';
import { User } from './user.schema';
@Controller('users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}
@Post()
async create(@Body() createUserDto: CreateUserDto): Promise<User> {
return this.usersService.create(createUserDto);
}
@Get()
async findAll(): Promise<User[]> {
return this.usersService.findAll();
}
@Get(':id')
async findOne(@Param('id') id: string): Promise<User> {
return this.usersService.findOne(id);
}
@Put(':id')
async update(@Param('id') id: string, @Body() updateUserDto: UpdateUserDto): Promise<User> {
return this.usersService.update(id, updateUserDto);
}
@Delete(':id')
async delete(@Param('id') id: string): Promise<User> {
return this.usersService.delete(id);
}
}
现在,我们把 UsersModule
加入到 AppModule
的imports数组里:
// src/app.module.ts
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import mongodbConfig from './configs/mongodb.config';
import { UsersModule } from './users/users.module';
@Module({
imports: [
MongooseModule.forRoot(mongodbConfig.uri),
UsersModule,
// ...其他模块
],
// ...其他配置
})
export class AppModule {}
到这里,我们已经完成了NestJS与MongoDB的集成,以及一个用户增加和查询功能的简单例子。通过这样的方式,我们便实现了在NestJS中针对MongoDB的增删改查操作。下面是每个操作对应的功能:
POST /users
创建用户GET /users
获取所有用户列表GET /users/:id
根据ID获取单个用户PUT /users/:id
根据ID更新用户信息DELETE /users/:id
根据ID删除用户集成NestJS和MongoDB是一个相对直接的过程,感谢NestJS对于Mongoose的封装,使得我们可以非常便捷地管理数据库操作和数据模型。同时,我们可以享受到TypeScript的类型安全和装饰器带来的元数据功效,使得数据库相关代码更加清晰易懂。希望本教程可以帮助你在项目中快速集成NestJS和MongoDB,并构建出强大的后端服务。