前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >10分钟上手nest.js+mongoDB

10分钟上手nest.js+mongoDB

作者头像
淼学派对
发布2024-04-10 09:23:51
1510
发布2024-04-10 09:23:51
举报
文章被收录于专栏:云开发小程序1云开发小程序1

废话不多说!

直接忽略掉没有用的理论!

实战!走起!

1.安装nest.js脚手架

代码语言:javascript
复制
cnpm i -g @nestjs/cli

2.创建nest项目

代码语言:javascript
复制
nest new 项目名

3.安装mongoose

项目中我们会用到 Mongoose 来操作我们的数据库,Nest 官方为我们提供了一个 Mongoose 的封装,我们需要安装 mongoose@nestjs/mongoose

代码语言:javascript
复制
npm install mongoose @nestjs/mongoose --save

4.创建模块

代码语言:javascript
复制
nest g module user server

脚手架工具会自动在 src/server/user 文件夹下创建一个 user.module.ts,这是 Nest 的模块文件,Nest 用它来组织整个应用程序的结构。

代码语言:javascript
复制
// user.module.ts
import { Module } from '@nestjs/common';
@Module({})
export class UserModule {}

同时还会在根模块 app.module.ts 中引入 UserModule 这个模块,相当于一个树形结构,在根模块中引入了 User 模块。

执行上面的终端命令之后,app.module.ts 中的代码已经发生了变化,在文件顶部自动引入了 UserModule,同时也在 @Module 装饰器的 imports 中引入了 UserModule

代码语言:javascript
复制
// app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { UserModule } from './server/user/user.module'; // 自动引入
@Module({
  imports: [UserModule], // 自动引入
  controllers: [AppController],
  providers: [AppService]
})
export class AppModule {}

5.创建控制器

代码语言:javascript
复制
nest g controller user server

Nest 中,controller 就类似前端的路由,负责处理客户端传入的请求服务端返回的响应

举个例子,我们如果要通过 http://localhost:3000/user/users 获取所有的用户信息,那么我们可以在 UserController 中创建一个 GET 方法,路径为 users 的路由,这个路由负责返回所有的用户信息。

代码语言:javascript
复制
// user.controller.ts
import { Controller, Get } from '@nestjs/common';
@Controller('user')
export class UserController {
  @Get('users')
  findAll(): string {
    return "All User's Info"; // [All User's Info] 暂时代替所有用户的信息
  }
}

这就是 controller 的作用,负责分发和处理请求响应

当然,也可以把 findAll 方法写成异步方法,像这样:

代码语言:javascript
复制
// user.controller.ts
import { Controller, Get } from '@nestjs/common';
@Controller('user')
export class UserController {
  @Get('users')
  async findAll(): Promise<any> {
    return await this.xxx.xxx(); // 一些异步操作
  }
}

6.创建 Provider

代码语言:javascript
复制
nest g service user server

provider 我们可以简单地从字面意思来理解,就是服务的提供者

怎么去理解这个服务提供者呢?

举个例子,我们的 controller 接收到了一个用户的查询请求,我们不能直接在 controller 中去查询数据库并返回,而是要将查询请求交给 provider 来处理,这里我们创建了一个 UserService,就是用来提供数据库操作服务的。

代码语言:javascript
复制
// user.service.ts
import { Injectable } from '@nestjs/common';
@Injectable()
export class UserService {}

当然,provider 不一定只能用来提供数据库的操作服务,还可以用来做一些用户校验,比如使用 JWT 对用户权限进行校验的策略,就可以写成一个策略类,放到 provider 中,为模块提供相应的服务。

controllerprovider 都创建完后,user.module.ts 文件中多了一些代码,变成了这样:

代码语言:javascript
复制
// 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 {}

7.连接数据库引入 根模块Mongoose

连接数据之前,我们要先在根模块,也就是 app.module.ts 中引入 Mongoose 的连接模块:

代码语言:javascript
复制
// 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:27017/Users'), UserModule],
  controllers: [AppController],
  providers: [AppService]
})
export class AppModule {}

如果这里运行后端文件是又可能会报错,如果报错就添加:

代码语言:javascript
复制
npm install @types/mongoose --dev

安装完之后服务就正常重启了。

8.引入 分模块Mongoose

这里我们先要创建一个数据表的格式,在 src/server/user 文件夹下创建一个 user.schema.ts 文件,定义一个数据表的格式:

代码语言:javascript
复制
// user.schema.ts
import { Schema } from 'mongoose';
export const userSchema = new Schema({
  _id: { type: String, required: true }, // 覆盖 Mongoose 生成的默认 _id
  user_name: { type: String, required: true },
  password: { type: String, required: true }
});

然后将我们的 user.module.ts 文件修改成这样:

代码语言:javascript
复制
// 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 {}

9.CRUD

创建两个文件做数据类型的定义:

user.interface.ts

代码语言:javascript
复制
// user.interface.ts
import { Document } from 'mongoose';
export interface User extends Document {
//   readonly _id: string;
  readonly user_name: string;
  readonly password: string;
}

user.dto.ts

代码语言:javascript
复制
// user.dto.ts
export class CreateUserDTO {
    readonly user_name: string;
    readonly password: string;
  }  
  export class EditUserDTO {
    readonly user_name: string;
    readonly password: string;
  }

我们打开 user.service.ts 文件,为 UserService 类添加一个构造函数,让其在实例化的时候能够接收到数据库 Model,这样才能在类中的方法里操作数据库。

代码语言:javascript
复制
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[]> {
        const users = await this.userModel.find();
        return users;
    }
    // 查找单个用户
    async findOne(user_name: string): Promise<User> {
        return await this.userModel.findOne({user_name});
    }
    // 添加单个用户
    async addOne(body: CreateUserDTO): Promise<void> {
        await this.userModel.create(body);
    }
    // 编辑单个用户
    async updateOne(user_name: string, newPassword: string): Promise<void> {
        await this.userModel.updateOne({user_name},{password: newPassword});
    }
    // 删除单个用户
    async deleteOne(user_name: string): Promise<void> {
        await this.userModel.deleteOne({user_name});
    }
}

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

现在,我们可以到 user.controller.ts 中设置路由了,将客户端的请求进行处理,调用相应的服务实现相应的功能:

代码语言:javascript
复制
import {
    Controller,
    Body,
    // Delete,
    Get,
    Param,
    Post,
    Put
} from '@nestjs/common';
import { CreateUserDTO, EditUserDTO } from './user.dto';
import { User } from './user.interface';
import { UserService } from './user.service';
interface UserResponse<T = unknown> {//这是一个 TypeScript 接口定义,用于描述用户响应的数据结构。它包含一个泛型参数 T,默认值为 unknown,其中包含 code(响应码)、data(响应数据,可选)和 message(响应消息)三个属性。
    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: '查询成功.'
        };
    }
    // GET /user/:_id
    @Post('/find_one')
    async findOne(@Body() userData: { user_name: string }): Promise<UserResponse> {
        await this.userService.findOne(userData.user_name); // 使用传入的 user_name 参数
        return {
            code: 200,
            data: await this.userService.findOne(userData.user_name),
            message: '查询成功.'
        };
    }
    // POST /user/user
    @Post('/user')
    async addOne(@Body() body: CreateUserDTO): Promise<UserResponse> {
        await this.userService.addOne(body);
        return {
            code: 200,
            message: '添加成功.'
        };
    }
    // PUT /user/:_id
    @Post('/upd')
    async updateOne(@Body() userData: { user_name: string, newPassword: string }): Promise<UserResponse> {
        await this.userService.updateOne(userData.user_name, userData.newPassword); // 使用传入的 user_name 参数
        return {
            code: 200,
            message: '修改成功.'
        };
    }
    // Post /user/deluser
    @Post('/deluser1')
    async deleteOne(@Body() userData: { user_name: string }): Promise<UserResponse> {
        await this.userService.deleteOne(userData.user_name); // 使用传入的 user_name 参数
        return {
            code: 200,
            message: '删除成功.'
        };
    }
}

好的,到这里我们的nest.js一个调用mongoose来操作mongoDB数据库的后端程序就已经写好了。

我们接下来用小程序端作为前端来调用后端,将整个完整的前后端+数据库程序跑起来!

10.前端部分

index.js

代码语言:javascript
复制
// pages/index1/index1.js
Page({

  /**
   * 页面的初始数据
   */
  data: {
  },
  // 增加

  // 输入框1的输入事件(姓名)
  input1Change(e) {
    this.setData({
      inputValue1: e.detail.value,
    });
  },

  // 输入框2的输入事件(年龄)
  input2Change(e) {
    this.setData({
      inputValue2: e.detail.value,
    });
  },
  tijiao(){
    wx.request({
      url: 'http://localhost:3000/user/user',
      method:'POST',
      data:{
        user_name:this.data.inputValue1,
        password:this.data.inputValue2
      },
    })
  },
  // 删除
  input1Change_del(e){
    this.setData({
      inputValue_del: e.detail.value,
    });
  },
  shanchu() {
    wx.request({
        url: 'http://localhost:3000/user/deluser1',
        method: 'POST',
        data: {
            user_name: this.data.inputValue_del,
        },
        success: (res) => {
            // 处理成功的情况
            console.log(res.data); // 可以打印后端返回的数据
        },
        fail: (error) => {
            // 处理失败的情况
            console.error(error);
        }
    })
},

  // 修改
  input1Change_upd(e){
    this.setData({
      inputValue1_upda: e.detail.value,
    });
  },
  input2Change_upd(e){
    this.setData({
      inputValue2_upda: e.detail.value,
    });
  },
  xiugai(){
    wx.request({
      url: 'http://localhost:3000/user/upd',
      method:'POST',
      data:{
        // 名字
        user_name:this.data.inputValue1_upda,
        // 修改后的年龄
        newPassword:this.data.inputValue2_upda,
      },
    })
  },
  // 查询
  input1Change_find(e){
    this.setData({
      inputValue1_find: e.detail.value,
    });
  },
  find(){
    wx.request({
      url: 'http://localhost:3000/user/find_one',
      method: 'POST',
      data:{
        // 名字
        user_name:this.data.inputValue1_find,
      },
      success: function(res) {
        // 请求成功,处理从服务器返回的数据
        console.log('服务器返回的数据:', res.data);

        // 检查是否找到匹配的记录
        if (res.data && res.data.length > 0) {
          // 处理返回的记录数据
          const records = res.data;
          records.forEach(record => {
            console.log('记录:', record);
            // 在这里进行您的处理逻辑,例如显示在界面上
          });
        } else {
          console.log('未找到匹配的记录');
          // 在界面上显示相应的消息,告知用户未找到匹配的记录
        }
      },
      fail: function(error) {
        // 请求失败,处理错误
        console.error('请求失败:', error);
        // 在界面上显示错误信息,告知用户请求失败
      }
    });
  },
  find_all(){
    wx.request({
      url: 'http://localhost:3000/user/users',
      method: 'GET',
      success: function(res) {
        // 请求成功,处理从服务器返回的数据
        console.log('服务器返回的数据:', res.data);

        // 检查是否找到匹配的记录
        if (res.data && res.data.length > 0) {
          // 处理返回的记录数据
          const records = res.data;
          records.forEach(record => {
            console.log('记录:', record);
            // 在这里进行您的处理逻辑,例如显示在界面上
          });
        } 
      },
      fail: function(error) {
        // 请求失败,处理错误
        console.error('请求失败:', error);
        // 在界面上显示错误信息,告知用户请求失败
      }
    });
  }
})
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-04-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.安装nest.js脚手架
  • 2.创建nest项目
  • 3.安装mongoose
  • 4.创建模块
  • 5.创建控制器
  • 6.创建 Provider
  • 7.连接数据库引入 根模块Mongoose
  • 8.引入 分模块Mongoose
  • 9.CRUD
  • 10.前端部分
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档