MongoDB
 sql >> Cơ Sở Dữ Liệu >  >> NoSQL >> MongoDB

Các ABC của NestJS:Hướng dẫn cho người mới bắt đầu với MongoDB (Mongoose).

NestJS là gì?

NestJS là một khung NodeJS hiện đại sử dụng các khung NodeJS phổ biến như Express và Fastify. NestJS phần lớn được lấy cảm hứng từ Angular và do đó, nó sử dụng một hệ thống mô-đun kiểu Angular. NestJS được viết bằng TypeScript, mặc dù nó cũng hỗ trợ JavaScript gốc.

Điều kiện tiên quyết

Để làm theo hướng dẫn này, bạn phải đáp ứng các yêu cầu sau

  • Năng lực trong PostMan hoặc bất kỳ công cụ kiểm tra API nào khác.
  • Kiến thức cơ bản về ứng dụng NodeJS và Express.
  • Kiến thức cơ bản về TypeScript.
  • Năng lực trong MongoDB (Mongoose).

Phần sau sẽ được cài đặt trên hệ thống của bạn

  • NodeJS v.14 trở lên.
  • Mã Visual Studio (Được khuyến nghị) hoặc bất kỳ IDE nào khác.
  • PostMan hoặc bất kỳ Công cụ kiểm tra API nào khác.

Các thuật ngữ phổ biến được sử dụng trong NestJS;

Dưới đây là một số thuật ngữ được sử dụng thường xuyên nhất trong NestJS mà bạn sẽ gặp nhiều trong bài viết này.

Giao diện

Giao diện là một định nghĩa kiểu. Do đó, nó được sử dụng như một trình kiểm tra / thực thi kiểu trong các hàm, lớp, v.v.

giao diện
interface humanInterface{
  name:string;
  gender:string;
  age:number;
}

const kevin: humanInterface={
  name:'Kevin Sunders',
  gender:'Male',
  age: 25,
}

humanInterface ở trên thực hiện kiểm tra kiểu nghiêm ngặt trên kevin vật. Typecript sẽ gây ra lỗi nếu bạn thêm một trường khác hoặc thay đổi kiểu của bất kỳ thuộc tính nào trong số các thuộc tính của đối tượng.

Bộ điều khiển

Các bộ điều khiển có nhiệm vụ tiếp nhận các yêu cầu gửi đến và phản hồi cho máy khách. Bộ điều khiển cộng tác với dịch vụ liên quan của nó.

Dịch vụ

Dịch vụ là một nhà cung cấp lưu trữ và truy xuất dữ liệu và được sử dụng với bộ điều khiển tương ứng của nó.

Người trang trí

Decorator là một biểu thức trả về hàm chấp nhận một target , nameproperty descriptor như là các đối số tùy chọn. Trình trang trí được viết là @decorator-name . Chúng thường được đính kèm với khai báo lớp, phương thức và tham số.

@Get()
   getAll(): Model[] {
    return this.testService.getAll();
  }

@Get trình trang trí ở trên đánh dấu khối mã bên dưới nó là GET yêu cầu. Tìm hiểu thêm về điều đó sau.

Mô-đun

Mô-đun là một phần của chương trình xử lý một tác vụ cụ thể. Một mô-đun trong NestJS được đánh dấu bằng cách chú thích một lớp được chú thích bằng @Module() người trang trí. Nest sử dụng siêu dữ liệu do @Module() cung cấp decorator để tổ chức cấu trúc ứng dụng.

Cài đặt CLI

Để bắt đầu, bạn sẽ phải cài đặt NestJS CLI **** với npm . Bạn có thể bỏ qua bước này nếu bạn đã cài đặt NestJS CLI trên hệ thống của mình.

npm i -g @nestjs/cli

Khối mã ở trên sẽ cài đặt CLI lồng trên toàn cầu trên hệ thống của bạn.

Tạo một dự án mới

Để tạo một dự án mới, hãy chạy nest new theo sau là tên dự án mong muốn của bạn. Đối với bài viết này, chúng tôi sẽ viết một API blog đơn giản với chức năng CRUD trong khi tuân thủ các tiêu chuẩn RESTful.

nest new Blog-Api

Lệnh này sẽ nhắc bạn chọn một trình quản lý gói, hãy chọn npm .

Sau đó, điều này sẽ mở đầu cho toàn bộ cấu trúc dự án với một điểm cuối API thử nghiệm có cổng được đặt thành 3000 theo mặc định. Bạn có thể kiểm tra nó tại http://localhost:3000 sau khi chạy npm run start:dev lệnh này sẽ khởi động máy chủ ở chế độ xem tương tự như những gì gật đầu thực hiện trong các ứng dụng express.

Sau khi kiểm tra điểm cuối, bạn sẽ cần xóa một số tệp mặc định vì bạn sẽ không cần chúng nữa. Để làm điều này;

  • mở thư mục src và bên trong,
  • xóa app.controller.spec.ts ,
  • xóa app.controller.ts ,
  • xóa app.service.ts ,
  • Mở app.module.ts ,
  • Xóa tham chiếu đến AppController trong controllers mảng và các lần nhập,
  • Xóa tham chiếu đến AppService trong providers mảng và các lần nhập.

Bạn cũng có thể cần thay đổi README.md để đáp ứng các thông số kỹ thuật của bạn.

app.module.ts của bạn tệp sẽ trông như thế này,

//app.module.ts

import { Module } from '@nestjs/common';

@Module({
  imports: [],
  controllers: [],
  providers: [],
})
export class AppModule {}

Biến môi trường

Thông lệ tốt, một số thông tin nhạy cảm trong mã của bạn không nên được công khai. Ví dụ:PORT của bạn và MongoDB URI của bạn .

Hãy sửa lỗi này trong mã của bạn.

Trên thiết bị đầu cuối của bạn chạy

npm i dotenv

Sau đó, tạo một .env tệp trong thư mục của bạn và thêm nó vào .gitignore của bạn tập tin. Lưu trữ PORT của bạn , bạn cũng sẽ phải lưu trữ MongoDB URI của mình sau này ở cùng một nơi. Bây giờ hãy thay thế PORT bị lộ trong main.ts của bạn tập tin. Để thực hiện việc này, hãy nhập dotenv gói và gọi .config() phương pháp trên đó.

import * as dotenv from 'dotenv';
dotenv.config();

Đây phải là main.ts của bạn sau khi bạn làm theo các bước ở trên.

//main.ts

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import * as dotenv from 'dotenv';
dotenv.config();

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(process.env.PORT);
}
bootstrap();

Tạo mô-đun

Để tạo mô-đun NestJS bằng NestJS CLI, hãy chạy đoạn mã bên dưới.

nest generate module blogs

Lệnh này tạo một blogs thư mục chứa blogs.module.ts tệp và đăng ký BlogsModule trong app.module.ts của bạn tệp.

Tạo giao diện

Hãy tạo giao diện bằng NestJS CLI để thực hiện việc kiểm tra loại đối tượng sẽ đại diện cho các bài đăng trên blog của bạn. Để đạt được điều này, trước tiên bạn phải cd vào blogs vì chúng được khuyến nghị lưu trữ gần các đối tượng miền mà chúng được liên kết.

cd src/blogs

Sau đó, chạy đoạn mã bên dưới để tạo giao diện.

nest generate interface blogs

điều này tạo ra một blogs.interface.ts tập tin. Đây là nơi chúng tôi sẽ xác định giao diện của mình. chúng tôi sẽ đặt tên giao diện là BlogsInterface .

export interface BlogsInterface {
  title: string;
  body: string;
  category: string;
  dateCreated: Date;
}

trước khi chạy thêm bất kỳ lệnh nào trên thiết bị đầu cuối của bạn, hãy nhớ cd ra khỏi src thư mục và trở lại thư mục gốc của bạn bằng cách chạy

cd ../..

Tạo dịch vụ &bộ điều khiển

Bạn sẽ cần tạo một lớp dịch vụ để lưu trữ và truy xuất dữ liệu cũng như xử lý tất cả logic và một lớp bộ điều khiển để xử lý tất cả các yêu cầu đến và phản hồi đi.

Dịch vụ

Để tạo một dịch vụ, hãy chạy lệnh dưới đây,

nest generate service blogs

Lệnh này tạo hai tệp blogs.service.spec.tsblogs.service.ts và đăng ký dịch vụ trong providers mảng trong blogs.module.ts .

Bộ điều khiển

Để tạo bộ điều khiển, hãy chạy lệnh bên dưới,

nest generate controller blogs

Lệnh này tạo hai tệp blogs.controller.spec.tsblogs.controller.ts và đăng ký bộ điều khiển trong controllers mảng trong blogs.module.ts .

Với những điều này, cấu trúc blog của bạn gần như hoàn chỉnh, bạn chỉ cần tạo BlogsService có thể truy cập vào các phần khác của chương trình của bạn. Bạn có thể đạt được điều này bằng cách tạo exports mảng trong blogs.module.ts gửi và đăng ký BlogsService trong mảng đó.

//blogs.module.ts

import { Module } from '@nestjs/common';
import { BlogsService } from './blogs.service';
import { BlogsController } from './blogs.controller';

@Module({
  providers: [BlogsService],
  controllers: [BlogsController],
  exports: [BlogsService],
})
export class BlogsModule {}

MongoDB (Mongoose).

Cài đặt mongoose bằng cách chạy,

npm install --save @nestjs/mongoose mongoose

Sau khi cài đặt, hãy nhập {MongooseModule} từ '@nestjs/mongoose’ vào app.module.ts của bạn tập tin. Sau đó lấy MongoDB URI của bạn và lưu trữ nó trong .env của bạn tập tin. Lặp lại các bước để nhập dotenv trong app.module.ts tập tin. Sau đó, trong imports gọi mảng .forRoot() phương thức lấy MongoDB URI của bạn làm đối số trên MongooseModule . Tương tự với mongoose.connect() trong các ứng dụng cấp tốc thông thường.

@Module({
  imports: [BlogsModule, MongooseModule.forRoot(process.env.MONGODB_URI)],

Tạo một lược đồ.

Hãy tạo một giản đồ để xác định hình dạng của các blog trong bộ sưu tập của chúng tôi. Để làm điều này,

  • Tạo một thư mục bên trong blogs của bạn thư mục, đặt tên cho nó là schemas ,
  • Bên trong các lược đồ schemas , tạo một tệp và gọi nó là blogs.schema.ts .

Sau đó,

Trước tiên, bạn sẽ phải,

  • Nhập prop decorator, Schema trình trang trí và SchemaFactory từ @nestjs/mongoose ,
  • Tạo một lớp Blog và xuất nó,
  • Chuyển lớp thành một Lược đồ bằng cách đặt @Schema() người trang trí phía trên lớp,
  • Tạo một BlogSchema không đổi , chỉ định giá trị trả về của việc gọi .createForClass(Blog) với tên lớp của bạn làm đối số trên SchemaFactory mà bạn đã nhập trước đó.
//blogs.schema.ts

import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';

@Schema()
export class Blog {}

export const BlogSchema = SchemaFactory.createForClass(Blog);

Sau đó, bạn sẽ cần xác định các thuộc tính của Lược đồ.

Để xác định một thuộc tính trong lược đồ, bạn sẽ cần đánh dấu từng thuộc tính bằng @prop() người trang trí. @prop decorator chấp nhận một đối tượng tùy chọn hoặc một khai báo kiểu phức tạp. Khai báo kiểu phức tạp có thể là mảng và khai báo kiểu đối tượng lồng nhau.

//blogs.schema.ts

import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';

@Schema()
export class Blog {
  @Prop({ required: true })
  title: string;

  @Prop({ required: true })
  body: string;

  @Prop({ required: true })
  category: string;

  @Prop({ required: true })
  dateCreated: Date;
}

export const BlogSchema = SchemaFactory.createForClass(Blog);

Nhập tiếp theo { Document } từ 'mongoose' .

Sau đó, tạo một kiểu liên hợp với lớp Giản đồ và Document đã nhập . Như vậy,

//blogs.schema.ts

import { Document } from 'mongoose';

export type BlogDocument = Blog & Document;

blogs.schema.ts cuối cùng của bạn tệp sẽ trông như thế này,

import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { Document } from 'mongoose';

export type BlogDocument = Blog & Document;

@Schema()
export class Blog {
  @Prop({ required: true })
  title: string;

  @Prop({ required: true })
  body: string;

  @Prop({ required: true })
  category: string;

  @Prop({ required: true })
  dateCreated: Date;
}

export const BlogSchema = SchemaFactory.createForClass(Blog);

Lược đồ đăng ký

Bạn sẽ cần nhập mọi thứ vào blogs.module.ts của mình tập tin. Để đạt được điều này, bạn cần phải,

  • Nhập {MongooseModule} từ '@nestjs/mongoose’ ,
  • Nhập {Blog, BlogSchema} từ './schemas/blogs.schema'
  • Tạo một imports mảng bên trong @module người trang trí
  • Gọi .forFeature() trên MongooseModule . Điều này đưa vào một mảng chứa một đối tượng xác định một name và một schema thuộc tính sẽ được đặt thành Blog.name của bạn và BlogSchema của bạn tương ứng.
@Module({
  imports: [
    MongooseModule.forFeature([{ name: Blog.name, schema: BlogSchema }]),
  ],

Lược đồ tiêm

Bạn sẽ cần đưa vào Blog mô hình thành blogs.service.ts bằng cách sử dụng @InjectModel() người trang trí. Để đạt được điều này, bạn sẽ phải

  • nhập { Model } từ 'mongoose' ,
  • nhập { InjectModel } từ '@nestjs/mongoose’ ,
  • Nhập {Blog, BlogDocument} từ './schemas/blogs.schema’ ,
  • Tạo một constructor bên trong BlogsService lớp học,
  • Khai báo một private biến và gọi nó là blogModel và gán một loại Model<BlogDocument> với nó. Tất cả các phương thức mongoose sẽ được gọi trên biến này.

Nhớ lại rằng, BlogDocument là kiểu kết hợp của Blog lớp và Model của Mongoose mà bạn đã tạo trước đó. Nó được sử dụng làm kiểu chung cho biến của bạn.

  • Trang trí blogModel với @InjectModel() và chuyển Blog.name như một đối số.
constructor(
    @InjectModel(Blog.name)
    private blogModel: Model<BlogDocument>,
  ) {}

Cách hoạt động của định tuyến

Đến đây chắc hẳn bạn đã nhận thấy rằng @Controller người trang trí có chuỗi 'blogs' truyền vào nó. Điều này có nghĩa là bộ điều khiển sẽ gửi tất cả các phản hồi và xử lý tất cả các yêu cầu được thực hiện trên http://localhost/3000/blogs .

Tiếp theo, bạn sẽ triển khai logic của bộ điều khiển và dịch vụ.

Dịch vụ và Logic điều khiển.

Cuối cùng đã đến lúc triển khai chức năng CRUD của bạn.

Trước khi bắt đầu, bạn cần thiết lập bộ điều khiển của mình. Bắt đầu bằng cách nhập một số HTTP bộ trang trí phương pháp vào bộ điều khiển của bạn.

//blogs.controller.ts

import {
  Controller,
  Body,
  Delete,
  Get,
  Post,
  Put,
  Param,
} from '@nestjs/common';

Sau đó, bạn sẽ cần nhập và đăng ký dịch vụ để có thể truy cập và nhập giao diện để kiểm tra loại.

//blogs.controller.ts

import { BlogsInterface } from './blogs.interface';
import { BlogsService } from './blogs.service';

Để đăng ký dịch vụ của bạn, hãy tạo một constructor bên trong BlogsController lớp và khai báo một private readonly dịch vụ service và đặt loại của nó thành BlogsService .

constructor(private readonly service: BlogsService) {}

Bây giờ bạn đã thiết lập xong, hãy bắt đầu.

Tạo

Logic dịch vụ

Nhập { BlogsInterface } từ './blogs.interface' và thêm một async chức năng của BlogsService lớp được gọi là createBlog , sẽ lấy một tham số blogs , với loại của nó là BlogInterface và kiểu trả về của nó là Promise với một <Blog> chung chung gõ phím.

async createBlog(blog: BlogsInterface): Promise<Blog> {
    return await new this.blogModel({
      ...blog,
      dateCreated: new Date(),
    }).save();
  }

Logic của bộ điều khiển

Trong BlogsController của bạn lớp thêm một async chức năng của lớp. Gọi nó là createBlog và đánh dấu nó bằng @Post decorator định nghĩa nó là một POST yêu cầu. createBlog lấy một tham số blogs , với loại của nó là BlogInterface . Đánh dấu tham số bằng @Body decorator trích xuất toàn bộ body đối tượng từ req đối tượng và điền thông số được trang trí bằng giá trị của body .

@Post()
  async createBlog(
    @Body()
    blog: BlogsInterface,
  ) {
    return await this.service.createBlog(blog);
  }

Đọc

Thêm hai async phương pháp, một để trả về một bài đăng trên blog và phương thức thứ hai để trả về tất cả các bài đăng trên blog.

Logic dịch vụ

async getAllBlogs(): Promise<Blog[]> {
    return await this.blogModel.find().exec();
  }

  async getBlog(id: string): Promise<Blog> {
    return await this.blogModel.findById(id);
  }

Logic của bộ điều khiển

  @Get()
  async getAllBlogs() {
    return await this.service.getAllBlogs();
  }

  @Get(':id')
  async getBlog(@Param('id') id: string) {
    return await this.service.getBlog(id);
  }

async các chức năng được đánh dấu bằng @Get decorator định nghĩa nó là một GET yêu cầu.

async thứ hai trình trang trí của hàm có đối số ':id' . Đó là những gì bạn sẽ chuyển vào @Param người trang trí. Tham số được đánh dấu bằng @Param('id') trích xuất params thuộc tính từ req đối tượng và điền thông số được trang trí bằng giá trị của params .

Cập nhật

Hãy triển khai logic cho PUT yêu cầu.

Logic dịch vụ

async updateBlog(id: string, body: BlogsInterface): Promise<Blog> {
    return await this.blogModel.findByIdAndUpdate(id, body);
  }

Logic của bộ điều khiển

@Put(':id')
  async updateBlog(
    @Param('id')
    id: string,
    @Body()
    blog: BlogsInterface,
  ) {
    return await this.service.updateBlog(id, blog);
  } 

async tham số thứ hai của hàm được đánh dấu bằng @Body() decorator trích xuất toàn bộ body đối tượng từ req đối tượng và điền thông số được trang trí bằng giá trị của body .

Xóa

Hãy triển khai logic cho delete yêu cầu.

Logic dịch vụ

async deleteBlog(id: string): Promise<void> {
    return await this.blogModel.findByIdAndDelete(id);
  }

Promise loại chung là void bởi vì một Delete yêu cầu trả về một lời hứa trống rỗng.

Logic của bộ điều khiển

@Delete(':id')
  async deleteBlog(@Param('id') id: string) {
    return await this.service.deleteBlog(id);
  }

Kiểm tra API

Để kiểm tra API này, bạn nên sử dụng công cụ kiểm tra API. Đối với bài viết này, tôi sẽ sử dụng một công cụ kiểm tra API phổ biến có tên là Postman. Tôi sẽ sử dụng dữ liệu ngẫu nhiên về các chủ đề phổ biến để kiểm tra.

Tạo

Tạo POST yêu cầu http://localhost/3000/blogs với các đối tượng JSON sau, điều này sẽ thêm tất cả dữ liệu vào cơ sở dữ liệu của bạn.

{
  "title": "jeen-yuhs",
  "body": "The life of superstar rapper Kanye West is currently streaming on Netflix - and according to our jeen-yuhs review, it's a fascinating watch. -credit:Radio Times",
  "category":"Music"
}

{
  "title": "Why You Should Always Wash Your Hands",
  "body": "Germs from unwashed hands can be transferred to other objects, like handrails, tabletops, or toys, and then transferred to another person's hands.-credit cdc.gov",
  "category":"Health"
}

{
  "title": "Why You Should Follow me on Twitter",
  "body": "Well, Because I asked nicely",
  "category":"Random"
}

Bạn sẽ nhận được 201 phản hồi và blog đã tạo với ngày tháng và _id đã thêm.

Đọc

Thực hiện GET yêu cầu http://localhost/3000/blogs . Điều này sẽ trả về một

200 phản hồi với một mảng của tất cả dữ liệu bạn đã thêm trước đó. Sao chép _id thuộc tính của một trong các đối tượng mảng.

Tạo một GET khác yêu cầu http://localhost/3000/blogs/id với id đã sao chép trước đó. Điều này sẽ trả về 200 phản hồi với dữ liệu của đối tượng có id được sử dụng để thực hiện yêu cầu.

Cập nhật

Tạo PUT yêu cầu http://localhost/3000/blogs/id với dữ liệu dưới đây. id nên được thay thế bằng cái bạn đã sao chép trước đó. Điều này sẽ trả về 200 phản hồi và cập nhật đối tượng mang id đằng sau hậu trường. nếu bạn chạy một GET khác yêu cầu bạn sẽ nhận được đối tượng cập nhật.

{
  "title": "why you Should Cut your Nails",
  "body": "It's important to trim your nails regularly. Nail trimming together with manicures makes your nails look well-groomed, neat, and tidy.- credit:WebMD",
  "category":"Health"
}

Xóa

Thực hiện DELETE yêu cầu http://localhost/3000/blogs/id . Điều này sẽ trả về 200 phản hồi và xóa đối tượng mang id đằng sau hậu trường. nếu bạn chạy một GET khác yêu cầu bạn sẽ không nhìn thấy đối tượng đã xóa.

Kết luận

Vì vậy, chúng tôi cuối cùng ở cuối bài viết này. Hãy tóm tắt lại những gì bạn đã đề cập.

  • NestJS là gì,
  • Các thuật ngữ trong NestJS,
  • Tạo ứng dụng NestJS,
  • Tích hợp MongoDB vào ứng dụng NestJS,
  • Thao tác và ứng dụng NestJS,

Đó là khá nhiều, chúc mừng bạn đã làm được điều này.

Bạn có thể tìm thấy mã trên github.

Chúc bạn may mắn trên hành trình NestJS!


  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Hỗ trợ giao dịch trong MongoDB

  2. Các toán tử mẫu MongoDB

  3. Làm thế nào để phát trực tuyến Kết quả truy vấn MongoDB với nodejs?

  4. Làm cách nào để định cấu hình một cụm MongoDB hỗ trợ các phiên?

  5. Cách tìm độ dài của mảng mongodb