ขณะนี้มี 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