ขณะนี้มี 3 ตัวเลือกในการใช้ Mongo กับ Node (และ NestJS)

เราจะพิจารณาแต่ละรายการและฉันจะยกตัวอย่างว่าคุณสามารถใช้ MongoDB ในแอปพลิเคชัน NestJS ของคุณได้อย่างไรโดยไม่ปวดหัว

1) NestJS + Mongoose ซึ่งบางทีบทช่วยสอนที่ดีที่สุดที่ฉันพบอยู่ที่นี่ https://scotch.io/tutorials/building-a-modern-app-using-nestjs-mongodb-and-vuejs ปัญหา คือฉันเกลียดความจริงที่ว่าฉันต้องเขียนคำจำกัดความของสคีมาและอินเทอร์เฟซ typescript หากคุณพอใจกับการเขียนทุกอย่าง 2 ครั้งใน Schema และเอกสารในรูปแบบ Typescript Interface บางทีนี่อาจเป็นวิธีที่ดีที่สุด!

2) NestJS + TypeORM ซึ่งคุณสามารถใช้ TypeORM กับ MongoDB ได้จริง แต่ฉันไม่แนะนำสิ่งนี้หากคุณต้องการเรียนรู้เพิ่มเติม ฉันจะขอให้คุณเขียนโพสต์ในบล็อกนี้ https://medium.com /articode/typeorm-mongodb-review-8855903228b1

3) NestJS + Typegoose — โดยพื้นฐานแล้ว สิ่งที่มันทำคือใช้อ็อบเจ็กต์โดเมนของคุณเพื่อรับสคีมาจากสิ่งเหล่านั้น และนี่คือสิ่งที่โพสต์นี้เกี่ยวกับ มีเอกสารมากมายที่คุณสามารถทำได้ อย่างไรก็ตาม ฉันไม่ชอบเอกสารส่วนใหญ่เลย มันแค่ดูเหมือนมีโค้ดมากเกินไป ยิ่งไปกว่านั้น บทช่วยสอนทั้งหมดยังรวมการใช้คลาส DTO ไว้ด้วยเสมอ และฉันไม่เห็นเหตุผลที่จะใช้คลาส DTO เลยใน 99% ของกรณีทั้งหมด DTO นั้นยอดเยี่ยม อย่าเข้าใจฉันผิด มีข้อดีมากมายในการใช้ DTO แต่ไม่มีบทช่วยสอนใดบนอินเทอร์เน็ตที่อธิบายได้ว่าทำไมพวกเขาต้องการ DTO และจริงๆ แล้วไม่มีใครต้องการ DTO เลย ดังนั้นฉันอยากจะเขียนวิธีที่ง่ายที่สุด วิธีที่ตรงไปตรงมาด้วย NestJS + MongoDB + และ TypeGoose

ก่อนอื่น เราจะติดตั้ง NestJS CLI โดย NestJS นั้นคล้ายกับ Angular มาก และแม้ว่าคุณจะไม่ชอบเชิงมุมก็ตาม เชื่อฉันเถอะว่าคุณจะชอบ NestJS เพราะจริงๆ แล้วฉันก็เหมือนกัน! อย่างไรก็ตาม บทช่วยสอนสำหรับผู้เริ่มต้นที่ยอดเยี่ยมสำหรับ NestJS คุณสามารถอ่านได้ที่นี่ ค้นหา https://scotch.io/tutorials/getting-started-with-nestjs

เริ่มต้นด้วยการสร้างแอป NestJS

npm ฉัน -g @nestjs/cli

จากนั้นสร้างโครงการ NestJS

ทำรังใหม่ Nestjspoc-Nest

ซีดี Nestjspoc-Nest

// เริ่มต้นแอปพลิเคชันโดยใช้ nodemon
npm run start:dev

เปิดเบราว์เซอร์ไปที่ localhost:3000 เพื่อตรวจสอบสวัสดีชาวโลกปรากฏขึ้น

ตกลง เราจะสร้างบริการและตัวควบคุมอย่างง่ายในโมดูล สมมติว่าแอปพลิเคชันของเราจะทำอะไรบางอย่างกับ Users และเราต้องการ UserModule ซึ่งจะเก็บวัตถุโดเมนผู้ใช้ บริการผู้ใช้ และตัวควบคุมผู้ใช้

ซ้อนสร้างผู้ใช้โมดูล

รังสร้างผู้ใช้บริการ
รังสร้างผู้ใช้คอนโทรลเลอร์

ตอนนี้คุณควรมีโฟลเดอร์ที่มี UserModule, UserService และ UserController

ซึ่งเกือบจะว่างเปล่า

Nest เราจะใช้ nestjs-typegoose เพราะมันทำให้ทุกอย่างง่ายขึ้น

การติดตั้ง npm - บันทึก Nestjs-typegoose

typegoose มีการพึ่งพาหลายเพียร์ ดังนั้นเราจึงจำเป็นต้องติดตั้งมันเช่นกัน การขึ้นต่อกันของ nestjs สองรายการที่เรามีอยู่แล้ว แต่เราต้องการอีกสองรายการ

"@typegoose/typegoose": "^6.0.0",
"@nestjs/common": "^6.3.1",
"@nestjs/core": "^6.3.1",
"mongoose": "^5.5.13"

สิ่งที่ทำเสร็จแล้ว package.json ของคุณควรมีลักษณะดังนี้:

{
  "name": "nestjspoc",
  "version": "0.0.1",
  "description": "",
  "author": "",
  "license": "MIT",
  "scripts": {
    "prebuild": "rimraf dist",
    "build": "nest build",
    "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
    "start": "nest start",
    "start:dev": "nest start --watch",
    "start:debug": "nest start --debug --watch",
    "start:prod": "node dist/main",
    "lint": "tslint -p tsconfig.json -c tslint.json",
    "test": "jest",
    "test:watch": "jest --watch",
    "test:cov": "jest --coverage",
    "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
    "test:e2e": "jest --config ./test/jest-e2e.json"
  },
  "dependencies": {
    "@nestjs/common": "^6.7.2",
    "@nestjs/core": "^6.7.2",
    "@nestjs/platform-express": "^6.7.2",
    "nestjs-typegoose": "^7.0.0",
    "rimraf": "^3.0.0",
    "rxjs": "^6.5.3",
    "@typegoose/typegoose": "^6.0.0",
    "mongoose": "^5.5.13"
  },
  "devDependencies": {
    "@nestjs/cli": "^6.9.0",
    "@nestjs/schematics": "^6.7.0",
    "@nestjs/testing": "^6.7.1",
    "@types/express": "^4.17.1",
    "@types/jest": "^24.0.18",
    "@types/node": "^12.7.5",
    "@types/supertest": "^2.0.8",
    "jest": "^24.9.0",
    "prettier": "^1.18.2",
    "supertest": "^4.0.2",
    "ts-jest": "^24.1.0",
    "ts-loader": "^6.1.1",
    "ts-node": "^8.4.1",
    "tsconfig-paths": "^3.9.0",
    "tslint": "^5.20.0",
    "typescript": "^3.6.3"
  },
  "jest": {
    "moduleFileExtensions": [
      "js",
      "json",
      "ts"
    ],
    "rootDir": "src",
    "testRegex": ".spec.ts$",
    "transform": {
      "^.+\\.(t|j)s$": "ts-jest"
    },
    "coverageDirectory": "./coverage",
    "testEnvironment": "node"
  }
}

สิ่งที่เราเพิ่มด้วยตนเองจะเป็นตัวหนา

นี่คือการตั้งค่า มาเขียนโค้ดกันดีกว่า

สร้างผู้ใช้อ็อบเจ็กต์โดเมนของคุณในไฟล์ user.ts เช่น:

import {prop, Typegoose} from '@typegoose/typegoose';

export class User extends Typegoose {
    @prop()
    name?: string;
}

คุณเห็นคำว่า @prop() ใช่แล้ว คุณต้องการสิ่งนี้ คุณสามารถเรียนรู้เพิ่มเติมเกี่ยวกับการตรวจสอบความถูกต้องและสิ่งที่คุณสามารถทำได้ในเอกสารประกอบของ typegoose
จากนั้นมาสร้างหรืออัปเดตคลาส UserService ของเรากันดีกว่า

import {Injectable} from '@nestjs/common';
import {User} from './domain/user';
import {InjectModel} from 'nestjs-typegoose';
import {ReturnModelType} from '@typegoose/typegoose';

@Injectable()
export class UserService {
    constructor(@InjectModel(User) private readonly userModel: ReturnModelType<typeof User>) {
    }

    async createCustomUser(user: User) {
        const createdUser = new this.userModel(user);
        return await createdUser.save();
    }

    async listUsers(): Promise<User[] | null> {
        return await this.userModel.find().exec();
    }
}

โอเค เวทมนตร์อันแรกอยู่ที่นี่แล้ว!

คุณอาจสังเกตเห็นบรรทัด @InjectModel(User) private readonly userModel: ReturnModelType ซึ่งจะให้ userModel ที่เราสามารถใช้กับประเภท User ของเราได้

createCustomUser และ listUsers ใช้ userModel นี้และฉันเชื่อว่ามันชัดเจนแค่ไหน :)

อัปเดต UserController ของเราต่อไป

import {Body, Controller, Get, Post} from '@nestjs/common';
import {UserService} from './user.service';
import {User} from './domain/user';

@Controller('user')
export class UserController {
    constructor(private readonly userService: UserService) { }

    @Get('listusers')
    async listUsers(): Promise<User[] | null> {
        return await this.userService.listUsers();
    }

    @Post('createuser')
    async createUser(@Body() cat: User): Promise<User> {
        return await this.userService.createCustomUser(cat);
    }
}

ไม่มีอะไรพิเศษที่นี่ เราเพียงแค่เพิ่มบริการของเรา และเราเรียกทั้งสองวิธีของเรา

เวทมนตร์อีกเล็กน้อย!

มีเวทย์มนตร์อีกสองบรรทัดที่คุณต้องเพิ่มใน UserModule และ AppModule ของคุณ

ในคำจำกัดความ UserModule เราจำเป็นต้องมีบรรทัดนี้ นำเข้า: [TypegooseModule.forFeature([User])]:

import { Module } from '@nestjs/common';
import { UserController } from './user.controller';
import { UserService } from './user.service';
import {User} from './domain/user';
import {TypegooseModule} from 'nestjs-typegoose';

@Module({
  imports: [TypegooseModule.forFeature([User])],
  controllers: [UserController],
  providers: [UserService],
})
export class UserModule {}

และใน AppModule เราจำเป็นต้องมีการกำหนดค่า Mongoose ของการนำเข้าสตริงการเชื่อมต่อ MongoDB:

การนำเข้า: <TypegooseModule.forRoot('mongodb://localhost:27017/nest')
โมดูลผู้ใช้],

import {Module} from '@nestjs/common';
import {AppController} from './app.controller';
import {AppService} from './app.service';
import {UserModule} from './user/user.module';
import {TypegooseModule} from 'nestjs-typegoose';

@Module({
    imports: [TypegooseModule.forRoot('mongodb://localhost:27017/nest'),
        UserModule],
    controllers: [AppController],
    providers: [AppService],
})
export class AppModule {
}

และใช่ คุณต้องมี MongoDB ถึงจะทำงาน ;)

แค่นั้นแหละ!

ทดสอบแล้ว - วิถีลิง !

สร้างผู้ใช้:

curl -X POST http://localhost:3000/user/createuser -H 'ประเภทเนื้อหา: application/json' -d '{ "ชื่อ": "Nayden Gochev" }'

และคุณจะได้รับ

{“_id”:”5dc00795d9a25df587a1e5f9,”ชื่อ”:”เนย์เดน โกเชฟ”,”__v”:0}

รายชื่อผู้ใช้ทั้งหมด:

curl -X รับ "http://localhost:3000/user/listusers"

บิตหายไป!

อะไรหายไป? แน่นอนว่าการตรวจสอบความถูกต้อง การรักษาความปลอดภัย และการทดสอบ ทั้งหมดนี้ — ครั้งต่อไป ;) ตอนนี้เป็นเวลาทำรัง

รหัสแหล่งที่มา

ซอร์สโค้ดเต็มสามารถดาวน์โหลดได้ที่นี่:
https://github.com/gochev/nest-js-poc-mongodb

เกี่ยวกับฉัน:

ฉันเป็น Java Developer ที่มีความรู้เกี่ยวกับ Spring มากมาย แต่เมื่อเร็วๆ นี้ ฉันต้องเขียน JavaScript แม้ว่าฉันจะไม่ต้องการก็ตาม ดังนั้นนั่นอาจอธิบายได้ว่าทำไมฉันถึงชอบ NestJS และใช่ การทำเช่นนี้ใน Java และ Spring นั้นง่ายกว่ามาก https://github.com/gochev/spring-mvc-poc-mongodb แต่ NestJS สนุกใช่ไหมล่ะ? :)

เผยแพร่ครั้งแรกที่ http://gochev.blogspot.com เมื่อวันที่ 4 พฤศจิกายน 2019