Nest.js connects to the MongoDB database

preface

When learning Nest and database connection, it is inevitable to encounter the problem of database selection. Here the author chooses MongoDB to record simple use. You can choose the right database according to different needs.

Post the following documents to facilitate further learning Nest Chinese documentation, MongoDB rookie tutorial


Database Introduction

  • MongoDB is a database based on distributed file storage. Written in C++ language. Designed to provide scalable high-performance data storage solutions for WEB applications.

  • MongoDB is a product between relational database and non-relational database. Among non-relational databases, it has the most rich functions and is the most like relational database.

Database selection

  • There are many mature databases on the market to choose from.

  • The conclusions the authors draw here are for big projects, according to various sourcesPostgreSqlSmall projects withMongoDBTherefore, the author plans to study together. This time, because I want to do a small project to practice my skills, I will use it firstMongoDBLet’s see what happens.
  • If you have different opinions, please discuss them in the comments section.

Configuring Basic Services

  • Make sure MongoDB is already installed on your computer

  • Remember to finish the environment configuration, you can boot from the start, you can also choose to start their own HHH look at the individual

Mongoose

  • Mongoose is a Nodejs driver library for MongoDB

  • MongoDB is a database, and Nodejs is a RUNNING environment of JS. Nodejs does not operate MongoDB directly. In this case, the corresponding driver is required to provide interfaces.

  • Install the dependencies in the Nest project, either way, of your choice

    $NPM install --save @nestjs/mongoose mongoose // NPM install $YARN add @nestjs/mongoose mongoose // YARN installCopy the code
  • We’ll introduce it in the AppModule file once the installation is complete

    /* app.module.ts */ import { Module } from '@nestjs/common'; import { AppController } from './app.controller'; import { AppService } from './app.service'; Import {UserModule} from './ USER /user.module'; Import {MongooseModule} from '@nestjs/ Mongoose '; @Module({// connect database imports: [UserModule, MongooseModule. ForRoot ('mongodb://localhost/test')], controllers: [AppController], providers: [AppService], }) export class AppModule {}Copy the code

Basic function module

  • We’ll use a User module for the demo

  • The basic functional modules I understand here include module(module) Controller(Controller) Service(provider) Schema(data model). We mainly use Nest to add, delete, modify and check MongoDB. These modules are sufficient for the time being.

  • A brief introduction to these modules:

  • concept Outlining the role
    The controller The declared route receives the response request and passes it on to the ‘provider’ for data processing
    The provider Generally, the method in the provider is called from the controller for data processing. In this case, the Schema method is used to add, delete, change and query the database
    Schema Define the structure of the documents within the collection, and the model is responsible for creating and reading from underneathMongoDBThe document.
    module NestUse it to organize the application structure, which should belong to the same application domain. Each function module has its own application domain, and Nest has a root module called app.module.ts
  • Since we’ve already introduced Mongoose to app.module.ts, the root module, let’s see what the functional module looks like

Schema

  • In Mongoose, everything comes from Scheme, and each Schema maps to a collection of MongoDB and defines the structure of the documents within the collection. Schema is used to define the model, which is responsible for creating and reading MongoDB’s documents from the bottom up.

  • Schemas can be created using NestJS’s built-in decorators, or you can do it yourself using the usual Mongoose approach. Using decorators to create schemas greatly reduces references and improves the readability of the code. Here the author uses the official recommended way to create with decorator, after all, with Nest should not use the point of characteristic HHH.

  • /* user.schema.ts */ import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; // @prop decorator takes an optional argument, by which you can indicate whether the property is required, whether a default value is required, or mark it as a constant, // SchemaFactory is a built-in method for Mongoose to read Schema documents and create a Schema object import {Document} from 'Mongoose '; export type UserDocument = User & Document; @Schema() export class User extends Document { @Prop() name: string; // Set the value to mandatory @prop ({required: true}) age: number; @Prop() height: number; } export const UserSchema = SchemaFactory.createForClass(User);Copy the code
  • Will be introduced in Module along with other features later.

Service

  • The purpose of the controller is to receive application-specific requests. The routing mechanism controls which controller receives which requests. Typically, each controller has multiple routes, and different routes can perform different operations.

    /* 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'; @InjectModel() export class UserService {// After Schema registration, the @InjectModel() decorator can be used to inject the User model into the UserService: Constructor (@injectModel ('User') private userTest: Model<UserDocument>) {} // Add async create(createUserDto: CreateUserDto): Promise<User> { const createUser = new this.userTest(createUserDto); const temp = await createUser.save(); return temp; } // find 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; } // delete async delete(sid: number) {const temp = await this.usertest. remove({_id: : {}} // delete async delete(sid: number) {const temp = await this.usertest. remove({_id: : {}) sid }); return temp; } // modify async updateUser(sid: string, data: Const temp = await this.usertest. updateOne({_id: sid}, {$set: data}); return temp; }}Copy the code
  • Will be introduced in Module along with other features later.

Controller

  • The purpose of the controller is to receive application-specific requests. The routing mechanism controls which controller receives which requests. Typically, each controller has multiple routes, and different routes can perform different operations.

    Import {Body, controller, Delete, Get, Param, Post, Put, Query } from '@nestjs/common'; Import {UserService} from './user.service'; Import {CreateUserDto} from './user.dto'; import {CreateUserDto} from '. @controller ('user') export class UserController {constructor(private readonly userService: UserService) {} // createUser route user/ createuser@post ('createUser') async createUser(@body () Body: CreateUserDto) { return this.userService.create(body); } @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); }}Copy the code

Moudle

  • Modules are classes with @Module() decorators. The @Module() decorator provides metadata that Nest uses to organize the application.

  • We introduced the above into our User module

    /* 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 provides forFeature() methods to configure modules, including defining which models should be registered in the current scope. // If you want to use this model in other modules, add MongooseModule to the exports section of the CatsModule and import the CatsModule in other modules. / / the name here: 'User' for injection in the database table name and the service is not the same as the table name corresponding to the complains imports: [MongooseModule. ForFeature ([{name: 'User' schema: UserSchema }])], controllers: [UserController], providers: [UserService], }) export class UserModule {}Copy the code
    • The above basic layout is complete, and the interface inspection can be carried out

The interface test

  • To handle these configurations, we also configured global routing in the main.ts fileapp.setGlobalPrefix('api'); This means that all requests will be preceded by one/api/
  • That’s what we use herePostManMongoDB CompassOfficial recommended visualization tool to view the effect

The POST to add

  • In this case, I’m using a POST request with a route of/API /user/createUser. I’m using application/json because I’m limiting the data type of the request parameters

  • Since the User data model we defined before is name,age,height, only these parameters are needed in the request, and other parameters cannot be added to the set even if written in

  • Postman

  • Open MongoDB Compass to view the data

  • You can see that we have already added one data to the database, and we are going to add two more for later query/delete/change operations

GET to check all

  • Here I’m using the GET request, and the route is/API /user/findAll because I’m looking up all the data in the user set, so I don’t need to add the request parameters

  • Postman

  • Open MongoDB Compass to view the data

  • As you can see, we have queried the database for the three pieces of data that we just added to the User set. Remember to REFRESH or the software won’t REFRESH itself

GET Displays a single user

  • Here I’m using the GET request, which is routed to/API /user/findOne because I’m looking for the data set in the user set that matches the search criteria, and here WE’re using name to query. It can also be queried with a unique value id.

  • Postman

  • As you can see, the returned result is a collection. For more information about how to query, see the official website

PUT change

  • Here I use PUT request and route it to/API /user/:sid because I want to limit the data type of the request parameter, I use application/json

  • Since the User data model we defined before is age and height, only these parameters are needed in the request, and other parameters cannot be added to the set even if written in. Here we pass in Xiaoming’s _id 61EEA1B4144eA374A5B8455A from the database into Param, and then put the content to be modified into the Body

  • Postman

  • Open MongoDB Compass to view the data

  • It can be seen that we have modified Xiaoming’s age and height

DELETE DELETE

  • Here I use the DELETE request with the route/API /user/:sid application/json because I want to limit the data type of the request parameters

  • Here we pass xiaoming’s _id 61EEa1b4144eA374a5b8455A into Param and initiate the request

  • Postman

  • Open MongoDB Compass to view the data

  • You can see that Xiaoming’s information no longer exists

conclusion

  • So far we have done inNest.jsThe use ofMongoose 对 MongoDBBasic operations on data. And finished using the decorator to create the data model in NestSchema
  • It also looks like you can use Nest’s built-in TypeORM to create your model. When I learn about other database connections, I will look through them and see how to operate them.
  • Nest still has a lot to learn, such as pipeline, middleware, interceptor, route guard, etc., which I plan to use in writing small demo to deepen my personal understanding. Otherwise, I will simply read documents and find it difficult to understand. So far I know that using pipes to do request type judgment is very sweet HHH interested partners can go to understand the next class validator

reference

  • Database classification and comparison of mainstream databases
  • Nest.js tutorial for the front end — 10 minutes of hands-on back-end interface development