在Nestjs(一)中前期准备中提到了安装MongoDB,此次就用MongoDB实现CRUD。

Start(回顾Nest的核心)
  • 创建Module : nest g mo user server
  • 脚手架工具会自动在 src/server/user 文件夹下创建一个 user.module.ts,这是 Nest 的模块文件,Nest 用它来组织整个应用程序的结构。
  • 会在根模块 app.module.ts 中:
  • 顶部引入 UserModule 模块,相当于一个树形结构,在根模块中引入了 User模块。
  • 同时也在@Module装饰器的 imports 中引入了UserModule
  • 创建 Controller: nest g co user server自动生成user.controller.ts文件,里面内容如下:
//user.controller.ts
import { Controller } from '@nestjs/common';
@Controller('user')
export class UserController {}

在Nest(一)中已经了解到controller 类似前端的路由,负责处理nestjs 部署到服务器 nestjs module_Nestjsnestjs 部署到服务器 nestjs module_Nestjs_02,所以是写接口的地方,举例子:

//user.controller.ts
 import { Controller,Get } from '@nestjs/common';
  @Controller('user')
  export class UserController {
  	@Get()
      findAll(): string {
        return 'All Users';
    }
  }
  • 创建 Provider:nest g s user server
// user.service.ts
  import { Injectable } from '@nestjs/common';
  @Injectable()
  export class UserService {}

注意:此时user.module.ts中的内容发生了变化:

// user.module.ts
import { Module } from '@nestjs/common';
import { UserController } from './user.controller';
import { UserService } from './user.service';
 
@Module({
  controllers: [UserController],
  providers: [UserService]
})
export class UserModule {}

连接数据库

  • 安装依赖
    在上次的项目基础上安装:
npm install --save mongoose @nestjs/mongoose
  • 根模块引入 Mongoose
// app.module.ts
  import { Module } from '@nestjs/common';
  import { MongooseModule } from '@nestjs/mongoose';
  import { AppController } from './app.controller';
  import { AppService } from './app.service';
  import { UserModule } from './server/user/user.module';
   
  @Module({
    imports: [MongooseModule.forRoot('mongodb://localhost/:aaa/prismaTest'), UserModule],
    controllers: [AppController],
    providers: [AppService]
  })
  export class AppModule {}

mongodb://localhost/:aaa/bbb是连接数据库的地址,aaa是数据库端口号,prismaTest是数据库名。

  • 引入其他模块
  • 先要创建一个数据表的格式,在src/server/user 文件夹下创建一个 user.schema.ts 文件,定义一个数据表的格式:
// user.schema.ts
import { Schema } from 'mongoose';
export const userSchema = new Schema({
   name: { type: String, required: true },
   password: { type: String, required: true },
   age: { type: Number, required: true },
   email: { type: String, required: true }
});
  • 修改user.module.ts
// user.module.ts
  import { Module } from '@nestjs/common';
  import { MongooseModule } from '@nestjs/mongoose';
  import { UserController } from './user.controller';
  import { userSchema } from './user.schema';
  import { UserService } from './user.service';
   
  @Module({
    imports: [MongooseModule.forFeature([{ name: 'Users', schema: userSchema }])],
    controllers: [UserController],
    providers: [UserService]
  })
  export class UserModule {}
  • 添加构造函数
    user.service.ts文件,为 UserService 类添加一个构造函数,让其在实例化的时候能够接收到数据库 Model,这样才能在类中的方法里操作数据库。
// user.service.ts
 import { Injectable } from '@nestjs/common';
 import { InjectModel } from '@nestjs/mongoose';
 import { Model } from 'mongoose';
 import { CreateUserDTO, EditUserDTO } from './user.dto';
 import { User } from './user.interface';
 
 @Injectable()
 export class UserService {
   constructor(@InjectModel('Users') private readonly userModel: Model<User>) {}
  
   // 查找所有数据
   async findAll(): Promise<User[]> {
     return  = await this.userModel.find();
   }
  
   // 查找单条数据
   async findOne(_id: string): Promise<User> {
     return await this.userModel.findById(_id);
   }
  
   // 添加单条数据
   async addOne(body: CreateUserDTO): Promise<User> {
     return await this.userModel.create(body);
   }
  
   // 编辑单条数据
   async editOne(_id: string, body: EditUserDTO): Promise<User> {
    return await this.userModel.findByIdAndUpdate( _id, body, { new: true });
   }
  
   // 删除单条数据
   async deleteOne(_id: string): Promise<User> {
     return await this.userModel.deleteOne({ _id: _id });
   }
 }

因为 mongoose 操作数据库其实是异步的,所以这里我们使用 async 函数来处理异步的过程。

到目前为止会报错,因为缺少文件user.interface.tsuser.dto.ts:

  • user.interface.ts
// user.interface.ts
 import { Document } from 'mongoose';
 
 export interface User extends Document {
     readonly name: string;
     readonly password: string;
     readonly age: number;
     readonly email: string;
 }
  • user.dto.ts (数据传输对象)
// user.dto.ts
  export class CreateUserDTO {
      readonly name: string;
      readonly password: string;
      readonly age: number;
      readonly email: string;
  }
  
  export class EditUserDTO {
      readonly name: string;
      readonly password: string;
      readonly age: number;
      readonly email: string;
  }

CRUD (设置路由)

  • nestjs 部署到服务器 nestjs module_User_03
//user.controller.ts
  import { Controller, Get, Post, Put, Body, Delete, Param } from '@nestjs/common';
  import { CreateUserDTO, EditUserDTO } from './user.dto';
  import { User } from './user.interface';
  import { UserService } from './user.service';
  interface UserResponse<T = unknown> {
      code: number;
      data?: T;
      message: string;
  }
  @Controller('user')
  export class UserController {
  	constructor(private readonly userService: UserService) { }
  	// GET /user/users
      @Get('users')
      async findAll(): Promise<UserResponse<User[]>> {
          return {
              code: 200,
              data: await this.userService.findAll(),
              message: 'Success.'
          };
      }
  }

nestjs 部署到服务器 nestjs module_ts_04

因为连接的是我之前使用过的数据库prismaTest,所以里面是有数据的。

  • nestjs 部署到服务器 nestjs module_js_05
    在查询的路由基础上加入下面增加的路由:
@Post()
async addOne(@Body() body: CreateUserDTO): Promise<UserResponse> {
   let result = await this.userService.addOne(body);
   return {
       code: 200,
       data: result,
       message: 'Success.'
   };
}

nestjs 部署到服务器 nestjs module_User_06

  • nestjs 部署到服务器 nestjs module_nestjs 部署到服务器_07
@Put(':_id')
  async editOne(
      @Param('_id') _id: string,
      @Body() body: EditUserDTO
  ): Promise<UserResponse> {
      let result = await this.userService.editOne(_id, body);
       return {
           code: 200,
           data: result,
           message: 'Success.'
       };
  }

将上面增加的_id为602253c4b6d3bd2a6b6d6ffa的数据的age改为18:

nestjs 部署到服务器 nestjs module_Nestjs_08

  • nestjs 部署到服务器 nestjs module_User_09
@Delete(':_id')
async deleteOne(@Param('_id') _id: string): Promise<UserResponse> {
    let result = await this.userService.deleteOne(_id);
    return {
        code: 200,
        data: result,
        message: 'Success.'
    };
}

删除上面增加的_id为602253c4b6d3bd2a6b6d6ffa的数据

nestjs 部署到服务器 nestjs module_js_10