用nest + mogodb + swagger 搭建一个简单的backend

1,720 阅读4分钟

前言

最近在做一个简单的后台模板,想先实现一个简单的RABC,想了一下,选择了使用nest,数据库方面,感觉还是用mogodb的话,来的方便点,毕竟算全自动了,用mysql可能开发体验还没这么爽。然后文档方面,集成swagger

创建应用

这个懂的都懂,就不啰嗦了,参考First steps

添加swagger服务

这一步还是比较简单的,首先加swagger的包:

pnpm i @nestjs/swagger swagger-ui-express

然后在main.ts中加入

image.png

运行后,差不多就是这个效果:

image.png

这就完成了,当然具体的配置,可以参考OpenAPI (Swagger) | NestJS - A progressive Node.js framework

添加mogodb服务

首先,得下个本地的mogodb服务,当然有条件可以买一个在线的,没条件的也可以白嫖一个免费在线的,在官方注册完,就能免费白嫖一个在线的,官网传送地址:Log in | MongoDB。当然,我比较专业,所以我选择下载一个本地的,传送地址MongoDB Compass | MongoDB。安装完之后,打开Compass,会有如下界面。

image.png

点击connect,就是一个默认的界面

image.png

当让这里我已经使用过了,所以有三个database。然后就是安装mogodb的包:

pnpm i @nestjs/mongoose mongoose

然后在app.module.ts上注册服务:

image.png

地址就是你本地的mogodb服务地址,然后加上你的database的名称,之后运行时,就会自动创建一个名称为admin的数据库了。

mogodb创建Schema

Schemamogodb的非常重要的一个概念,实现了document创建,查询删除等操作,接下来演示如何创建一个Schema,并插入一条数据。

1.创建schema

先添加schemasservices两个文件夹: image.png

2.创建一个Role Schema

schema文件夹下添加role.ts,并添加如下代码:

import { Prop, SchemaFactory, Schema } from '@nestjs/mongoose';
import mongoose, { Document } from 'mongoose';
import { Menu } from './menu';

export type RoleDocument = Role & Document;

@Schema()
export class Role {
    @Prop()  //指明schema的属性
    roleName: string;
    
    //这是一个链接属性,可以理解为外键
    @Prop({ type: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Menu' }] })
    menus: Menu[];
}

export const RoleSchema = SchemaFactory.createForClass(Role); //创建schema

3.创建一个role服务

services文件夹下面添加role.ts,并添加如下代码:

import { Model } from 'mongoose';
/*
https://docs.nestjs.com/providers#services
*/

import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Role, RoleDocument } from '@schemas/role';
import { CreateRoleDto } from '@dto/role/mogodb/create-role.dto';
import { UpdateRoleDto } from '@dto/role/mogodb/update-role-dto';

@Injectable()
export class RoleService {
    constructor(
        @InjectModel(Role.name) private roleModel: Model<RoleDocument>,
    ) {}

    async create(createRoleDto: CreateRoleDto) {
        return (await this.roleModel.create(createRoleDto)).save();
    }

    async updateById(updateRoleDto: UpdateRoleDto) {
        return await this.roleModel.findByIdAndUpdate(
            updateRoleDto._id,
            updateRoleDto,
        );
    }

    async getPageRole(pageIndex: number, pageSize: number) {
        return this.roleModel
            .find()
            .skip(pageIndex - 1)
            .limit(pageSize);
    }

    async getAllRole() {
        return await this.roleModel.find().exec();
    }

    async getRoleById(id: string) {
        return await this.roleModel.findById(id).exec();
    }

    async deleteRoleById(id: string) {
        return await this.roleModel.findByIdAndDelete(id);
    }

    async deleteRoleMany(id: string[]) {
        return await this.roleModel.findByIdAndDelete(id);
    }
}

当然我在这里已经写了一些基本的增删改了,大家即兴参考。

4.创建Role Controller并注入RoleSchema

创建controller这一步,相信大家懂的都懂,就不罗嗦了。重点是在role.module.ts加入RoleSchema:

import { Role, RoleSchema } from '@schemas/role';
import { RoleService } from '@services/role.service';
/*
https://docs.nestjs.com/modules
*/

import { RoleController } from '@controllers/role.controller';
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';

@Module({
    imports: [
        MongooseModule.forFeature([{ name: Role.name, schema: RoleSchema }]),
    ],
    controllers: [RoleController],
    providers: [RoleService],
})
export class RoleModule {}

然后我们的Role Services才能在控制器中正常使用。 接下来是控制器的代码,我就直接上代码,当然我已经在swagger上添加了额外的处理,还加了个VO对象,大家自行参考:

/*
https://docs.nestjs.com/controllers#controllers
*/

import { JwtAuthGuard } from '@core/auth/guards/jwt-auth.guard';
import { AdminResponse } from '@core/utils';
import { AdminApiExtraModels } from '@decorator/admin-api-extra-models.decorator';
import { AdminApiResponse } from '@decorator/admin-api-response.decorator';
import { AdminController } from '@decorator/admin-controller.decorator';
import { GetPageRoleRes } from '@dto/role/view/get-page-role.res';
import { InsertRoleData } from '@dto/role/view/insert-role.data';
import { UpdateRoleData } from '@dto/role/view/update-role.data';
import { Body, Get, Post, Query, UseGuards } from '@nestjs/common';
import {
    ApiBearerAuth,
    ApiOperation,
    ApiQuery,
    ApiTags,
    getSchemaPath,
} from '@nestjs/swagger';
import { RoleService } from '@services/role.service';

@ApiTags('role')
@ApiBearerAuth()
@AdminApiExtraModels(GetPageRoleRes, UpdateRoleData)
@AdminController('role')
export class RoleController {
    constructor(private readonly roleService: RoleService) {}

    @UseGuards(JwtAuthGuard)
    @ApiOperation({ summary: '插入角色' })
    @Post('insertRole')
    async insertRole(@Body() insertRoleData: InsertRoleData) {
        await this.roleService.create(insertRoleData);
        return AdminResponse.success('插入成功');
    }

    @UseGuards(JwtAuthGuard)
    @ApiOperation({ summary: '获取角色' })
    @AdminApiResponse({ items: { $ref: getSchemaPath(GetPageRoleRes) } })
    @ApiQuery({ required: false, name: 'pageSize' })
    @ApiQuery({ required: false, name: 'pageIndex' })
    @Get('getPageRole')
    async getPageRole(
        @Query('pageSize') pageSize: number,
        @Query('pageIndex') pageIndex: number,
    ) {
        return this.roleService.getPageRole(pageIndex, pageSize);
    }

    @UseGuards(JwtAuthGuard)
    @ApiOperation({ summary: '获取全部角色' })
    @AdminApiResponse({ items: { $ref: getSchemaPath(GetPageRoleRes) } })
    @Get('getAllRole')
    async getAllRole() {
        const resData = await this.roleService.getAllRole();
        return AdminResponse.success('获取成功', resData);
    }

    @UseGuards(JwtAuthGuard)
    @ApiOperation({ summary: '更新角色' })
    @AdminApiResponse({ $ref: getSchemaPath(GetPageRoleRes) })
    @Post('updateRole')
    async updateRole(@Body() updateData: UpdateRoleData) {
        await this.roleService.updateById(updateData);
        return AdminResponse.success('更新成功');
    }

    @UseGuards(JwtAuthGuard)
    @ApiOperation({ summary: '获得权限菜单' })
    @AdminApiResponse({ $ref: getSchemaPath(GetPageRoleRes) })
    @Get('getRoleMenu')
    async getRoleMenu(@Query('id') id: string) {
        const menus = (await this.roleService.getRoleById(id)).menus;
        return AdminResponse.success('获取成功', menus);
    }

    @UseGuards(JwtAuthGuard)
    @ApiOperation({ summary: '删除角色' })
    @AdminApiResponse({ type: 'string' })
    @Post('deleteRoleMany')
    async deleteRoleMany(@Body() deleteRoleManyData: string[]) {
        await this.roleService.deleteRoleMany(deleteRoleManyData);
        return AdminResponse.success('删除成功');
    }
}

体验时刻

终于到了激动的run环节了,测试一下,这个简单搭建的nest应用,当然实际上我已经把鉴权也加上了,登录环节我就跳过了,测试一下role,先搞个插入: image.png

看一下Compass:

image.png

可以看到插入成功了。

再来测个查询:

image.png

可以看到swagger也成功返回了,其中还包含了刚才创建的test。到这里,一个nest + mogodb + swagger的应用就简单成功了,当然还有一些细节我没讲,不过都是一些返回处理的,这个因人而异,以上代码具体参考: radium-vue-admin/admin-backend

感觉有帮助的话,给个star,好让我找下一份工作时吹个