node中怎么使用Nest.js 连接 MongoDB 数据库?下面本篇文章给大家介绍一下node 框架 Nest.js 使用 MongoDB 的方法,希望对大家有所帮助!
在学习 Nest 与数据库进行连接时,难免会遇到选择数据库的问题,这里作者选择的是 MongoDB
记录一下简单使用。 大家可以根据不同需求选择合适的数据库。
贴出跟进看的文档以方便大家进一步学习 Nest 中文文档 ,MongoDB菜鸟教程
数据库简介
-
MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。
-
MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。
数据库选择
- 目前市面上有很多成熟的数据库可供大家选择。
- 据翻看各种资料作者这里得出的结论为大项目用
PostgreSql
小项目用MongoDB
所以作者准备一起学习下,这次因为想做一个小项目练练手所以先用MongoDB
看看怎么样。 - 大家有不同看法欢迎在评论区讨论。
配置基本服务
-
确保电脑已经安装了
MongoDB
没 -
记得弄完做一下环境配置,可以开机自启, 也可以选择自己启动哈hhh看个人
Mongoose
-
简单介绍一下 ,
Mongoose
是一个操作MongoDB
的Nodejs
驱动库 -
MongoDB
是数据库,Nodejs
是js的一个运行环境,Nodejs
不直接操作Mongodb
,这个时候就需要相应的驱动程序来提供接口。 -
在 Nest 项目中安装一下依赖项,两种安装方式,自行选择
$ npm install --save @nestjs/mongoose mongoose // NPM 安装 $ yarn add @nestjs/mongoose mongoose // YARN 安装复制代码
-
安装完成后我们在 AppModule 文件中引入一下
/* app.module.ts */ import { Module } from '@nestjs/common'; import { AppController } from './app.controller'; import { AppService } from './app.service'; // 我自己准备的 USER 模块 import { UserModule } from './user/user.module'; // 引入 Mongoose import { MongooseModule } from '@nestjs/mongoose'; @Module({ // 用 forRoot 方法连接数据库 imports: [UserModule, MongooseModule.forRoot('mongodb://localhost/test')], controllers: [AppController], providers: [AppService], }) export class AppModule {}
基础功能模块
-
这里用一个 User 模块来做 demo
-
这里我理解的基础功能模块包括
module
(模块)Controller
(控制器)Service
(提供者)Schema
(数据模型) 我们主要是用Nest对
MongoDB
做增删改查 这几个模块目前暂时够用。 -
对这几个模块做一些简单介绍:
-
由于我们上面已经对 app.module.ts 该根模块已经引入过了
mongoose
所以下面我们之间看一下功能模块是怎样的
Schema
-
在
Mongoose
中,一切都源于 Scheme,每个Schema
都会映射到MongoDB
的一个集合,并定义集合内文档的结构。Schema
被用来定义模型,而模型负责从底层创建和读取MongoDB
的文档。 -
Schema
可以用NestJS
内置的装饰器来创建,或者也可以自己动手使用Mongoose
的常规方式。使用装饰器来创建Schema
会极大大减少引用并且提高代码的可读性。这里作者用的是官方推荐方式用装饰器来创建,毕竟用的是 Nest 不得用点特色的hhh。 -
/* user.schema.ts */ import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; // @Prop 装饰器接受一个可选的参数,通过这个,你可以指示这个属性是否是必须的,是否需要默认值,或者是标记它作为一个常量,下面是例子 // SchemaFactory 是 mongoose 内置的一个方法做用是读取模式文档 并创建 Schema 对象 import { Document } from 'mongoose'; export type UserDocument = User & Document; @Schema() export class User extends Document { @Prop() name: string; // 设置值为必填 @Prop({ required: true }) age: number; @Prop() height: number; } export const UserSchema = SchemaFactory.createForClass(User);
-
等下和其他功能一起在 Module 中引入。
Service
-
控制器的目的是接收应用的特定请求。路由机制控制哪个控制器接收哪些请求。通常,每个控制器有多个路由,不同的路由可以执行不同的操作。
/* user.service.ts */ import { Model } from 'mongoose'; import { InjectModel } from '@nestjs/mongoose'; import { User, UserDocument } from 'src/schema/user.schema'; import { CreateUserDto } from './user.dto'; @Injectable() export class UserService { // 注册Schema后,可以使用 @InjectModel() 装饰器将 User 模型注入到 UserService 中: constructor(@InjectModel('User') private userTest: Model<UserDocument>) {} // 添加 async create(createUserDto: CreateUserDto): Promise<User> { const createUser = new this.userTest(createUserDto); const temp = await createUser.save(); return temp; } // 查找 async findAll(): Promise<User[]> { // 这里是异步的 const temp = await this.userTest.find().exec(); return temp; } // 查找 async findOne(name: string): Promise<User[]> { // 这里是异步的 const temp = await this.userTest.find({ name }); return temp; } // 删除 async delete(sid: number) { // 这里是异步的 remove 方法删除成功并返回相应的个数 const temp = await this.userTest.remove({ _id: sid }); return temp; } // 修改 async updateUser(sid: string, data: any) { // 这里是异步的 remove 方法删除成功并返回相应的个数 const temp = await this.userTest.updateOne({ _id: sid }, { $set: data }); return temp; } }
-
等下和其他功能一起在 Module 中引入。
Controller
-
控制器的目的是接收应用的特定请求。路由机制控制哪个控制器接收哪些请求。通常,每个控制器有多个路由,不同的路由可以执行不同的操作。
/* user.controller.ts */ // 引入 Nest.js 内置的各个功能 import { Body, Controller, Delete, Get, Param, Post, Put, Query } from '@nestjs/common'; // 引入用户服务 import { UserService } from './user.service'; // 引入创建用户 DTO 用于限制从接口处传来的参数 import { CreateUserDto } from './user.dto'; // 配置局部路由 @Controller('user') export class UserController { constructor(private readonly userService: UserService) {} // 创建user路由 user/createUser @Post('createUser') async createUser(@Body() body: CreateUserDto) { return this.userService.create(body); } //查找所有 user 路由 @Get('findAll') async findAll() { return this.userService.findAll(); } // 查找某一个用户路由 @Get('findOne') async findOne(@Query() query: any) { return this.userService.findOne(query.name); } // 删除一个用户的路由 @Delete(':sid') deleteUser(@Param() param: any) { return this.userService.delete(param.sid); } // 更改用户信息的路由 @Put(':sid') updateUser(@Body() body: any, @Param() param: any) { return this.userService.updateUser(param.sid, body); } }
Moudle
-
模块是具有
@Module()
装饰器的类。@Module()
装饰器提供了元数据,Nest 用它来组织应用程序结构。 -
我们把以上内容引入到我们的 User 模块中
/* user.module.ts */ import { Module } from '@nestjs/common'; import { UserController } from './user.controller'; import { UserService } from './user.service'; import { MongooseModule } from '@nestjs/mongoose'; import { UserSchema } from 'src/schema/user.schema'; @Module({ // MongooseModule提供了forFeature()方法来配置模块,包括定义哪些模型应该注册在当前范围中。 // 如果你还想在另外的模块中使用这个模型,将MongooseModule添加到CatsModule的exports部分并在其他模块中导入CatsModule。 // 这里的 name:'User' 为数据库表名称与 service 中注入的表名称对应两者不一样会报错 imports: [MongooseModule.forFeature([{ name: 'User', schema: UserSchema }])], controllers: [UserController], providers: [UserService], }) export class UserModule {}
- 以上我们的基础布局完成,可以进行接口检验了
接口检验
- 处理这些配置我们还在 main.ts 文件中配置了全局路由
app.setGlobalPrefix('api');
意思就是所有请求前面会有一个/api/
- 这里我们用的
PostMan
和MongoDB Compass
官方推荐的可视化工具查看效果
POST 增
-
这里我使用
POST
请求,路由为/api/user/createUser
因为要限制请求参数的数据类型所以这里方式为application/json
-
因为这里我们之前定义的 User 数据模型为 name,age,height, 所以请求里面只需要这几个参数即可,别的就算写进去也添加不到集合中
-
Postman
-
打开 MongoDB Compass 查看数据
-
可以看到我们已经添加到数据库中一条数据,接下来我们在添加两条,方便等会的查询/删除/更改操作
GET 查所有
-
这里我使用
GET
请求,,路由为/api/user/findAll
因为这里是查 User 集合内所有数据,所以不用添加请求参数 -
Postman
-
打开 MongoDB Compass 查看数据
-
可以看到我们已经查询到数据库中刚才在
User
集合中添加的三条数据切记要点REFRESH
建不然软件不会自己刷新
GET 查单个用户
-
这里我使用
GET
请求,路由为/api/user/findOne
因为这里是查 User 集合内对应搜索条件的数据集合,这里我们用的是name 去查询的。也可以用唯一值 id 去查询。 -
Postman
-
可以看到返回结果是一个集合,了解