Sử dụng NestJS và MongoDB để xây dựng API GraphQL
GraphQL và NestJS tạo nên mối quan hệ hợp tác tuyệt vời, mang đến cho bạn nền tảng vững chắc cho các API của bạn và một khung dễ sử dụng để xây dựng các ứng dụng web có thể mở rộng. Sự kết hợp này là hoàn hảo để xây dựng các ứng dụng sẵn sàng sản xuất và cả hai đều là những công cụ rất phù hợp trong hệ sinh thái công nghệ ngày nay.
Tìm hiểu thêm về cách bạn có thể tạo API bằng cách sử dụng cả hai sản phẩm.
Mục Lục
GraphQL là gì?
GraphQL là ngôn ngữ thao tác và truy vấn dữ liệu mà bạn có thể sử dụng để xây dựng API theo cách chính xác và ngắn gọn hơn. GraphQL cung cấp mô tả đầy đủ và đầy đủ về dữ liệu hiện có trong API và cung cấp khả năng cho khách hàng để lấy dữ liệu chính xác cần thiết.
GraphQL cung cấp nhiều tính năng mà API REST thiếu, từ truy vấn dữ liệu chính xác đến công cụ dành cho nhà phát triển tốt hơn, chẳng hạn như trình chỉnh sửa graphiql. Nó cũng cho phép bạn truy vấn nhiều tài nguyên thông qua một yêu cầu.
NestJS là gì?
NestJS là một khung công tác Node.js tiến bộ mà bạn có thể sử dụng để xây dựng các ứng dụng phía máy chủ có thể mở rộng và hiệu quả. NestJS cung cấp nhiều plugin, bên cạnh công cụ để phát triển nhanh chóng và dễ dàng bao gồm hỗ trợ GraphQL, GRPC, WebSockets, v.v.
NestJS nổi tiếng trong hệ sinh thái nhờ cấu trúc dự án được tối ưu hóa bằng cách sử dụng các mô-đun, bộ điều khiển, dịch vụ và lược đồ. CLI tích hợp của nó cho phép bạn tạo kiến trúc API có cấu trúc. Bạn có thể sử dụng các nguyên tắc tiêm phụ thuộc để kiểm soát cách các phần của ứng dụng giao tiếp với nhau.
Triển khai GraphQL với NestJS và MongoDB
Trước khi xây dựng một API với NestJS và GraphQL, bạn cần có sẵn các phần phụ thuộc phù hợp. Bạn cần cài đặt Node.js và NestJS, bạn có thể cài đặt bằng cách chạy npm tôi -g @nestjs/cli.
Ví dụ sau đây là một ứng dụng đơn giản lưu trữ thông tin về sách. Chạy lệnh sau trong thiết bị đầu cuối của bạn để tạo ứng dụng NestJS mới:
nest new <app-name>
Điều hướng đến thư mục của ứng dụng đã tạo (
$ npm install --save @nestjs/config @nestjs/graphql graphql-tools graphql
@nestjs/apollo apollo-server-express @nestjs/mongoose @types/graphql
Có hai cách tiếp cận chính để xây dựng API GraphQL, đó là:
- Cách tiếp cận lược đồ đầu tiên: nơi bạn mô tả API trong các tệp định nghĩa lược đồ hoặc SDL và NestJS tạo các định nghĩa Bản mô tả dựa trên chúng.
- Cách tiếp cận mã đầu tiên: nơi bạn xác định các truy vấn, đột biến và các chức năng GraphQL khác bằng cách sử dụng các lớp Typescript và trình trang trí, đồng thời NestJS tạo các tệp SDL dựa trên chúng.
Ví dụ sau đây mô tả cách sử dụng phương pháp ưu tiên mã.
Trước tiên, bạn cần khởi tạo GraphQL trong Mô-đun ứng dụng và kết nối nó với cơ sở dữ liệu MongoDB:
import { Module } from '@nestjs/common';
import { GraphQLModule as NestGraphQLModule } from '@nestjs/graphql';
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
import { join } from 'path';
import { MongooseModule } from '@nestjs/mongoose';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ConfigModule, ConfigService } from '@nestjs/config';
import mongodbConfig from './config/mongodb.config';@Module({
imports: [
ConfigModule.forRoot({
load: [mongodbConfig],
isGlobal: true
}),
NestGraphQLModule.forRootAsync<ApolloDriverConfig>({
driver: ApolloDriver,
inject: [ConfigService],
useFactory: async (configService: ConfigService) => ({
autoSchemaFile: join(process.cwd(), 'src/schema.gql'),
installSubscriptionHandlers: true,
sortSchema: true,
playground: true,
debug: configService.get<boolean>("DEBUG"),
uploads: false,
}),
}),
MongooseModule.forRootAsync({
inject: [ConfigService],
useFactory: async (configService: ConfigService) => ({
uri: configService.get('MONGO_URI')
})
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
Mô-đun này nhập khẩu Mô-đun GraphQL từ @nestjs/graphql và MongooseMô-đun từ @nestjs/cầy mangut giúp kết nối với MongoDB. Các autoSchemaFile thuộc tính chỉ định vị trí của tệp lược đồ được tạo và thuộc tính sắp xếpSchema đảm bảo rằng nó sắp xếp các trường theo thứ tự bảng chữ cái.
Đây là những gì MongoDB của bạn cấu hình tập tin sẽ giống như:
import { registerAs } from '@nestjs/config';
* Mongo database connection config
*/
export default registerAs('mongodb', () => {
const {
MONGO_URI
} = process.env;
return {
uri: `${MONGO_URI}`,
};
});
Xác định lược đồ GraphQL
Sau khi thiết lập các kết nối GraphQL và MongoDB, bạn nên xác định các truy vấn và thay đổi GraphQL để tạo một lược đồ (lược đồ.gql) tài liệu.
Viết truy vấn
bên trong cách tiếp cận mã đầu tiênbạn tạo một mô hình bằng cách sử dụng Loại đối tượng người trang trí. Sau đó, bạn sẽ chuyển đổi mô hình này thành một loại GraphQL.
Ví dụ:
import { Field, ObjectType } from '@nestjs/graphql';
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { Document } from 'mongoose';export type BookDocument = Book & Document;
@ObjectType()
@Schema()
export class Book {
@Field()
title: string;
@Field()
author: string;
@Field()
publishedDate: boolean;
}
export const BookSchema = SchemaFactory.createForClass(Book);
Theo mặc định, GraphQL không thể sử dụng các lược đồ đã tạo. Để làm cho chúng hoạt động, bạn cần một dịch vụ trình phân giải chứa các hàm để thực thi các loại GraphQL. Bạn có thể làm như vậy với người giải quyết người trang trí.
import { Resolver, Query, Mutation, Args, ID } from '@nestjs/graphql';
import { Book } from './book.model';
import { BookService } from './books.service';@Resolver(() => Book)
export class BookResolver {
constructor(private readonly bookService: BookService) { }
@Query(() => [Book])
async books(): Promise<Book[]> {
return this.bookService.findAll();
}
@Query(() => Book)
async book(@Args('id', { type: () => ID }) id: string): Promise<Book> {
return this.bookService.findOne(id);
}
}
Bạn có thể thực hiện các SáchDịch vụ, nhập khẩu ở trên, như sau:
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { Book, BookDocument } from './book.model';@Injectable()
export class BookService {
constructor(@InjectModel(Book.name) private bookModel: Model<BookDocument>) { }
async findAll(): Promise<Book[]> {
return this.bookModel.find().exec();
}
async findOne(id: string): Promise<Book> {
return this.bookModel.findById(id).exec();
}
}
Bạn cũng cần thêm BookResolver vào danh sách các nhà cung cấp trong sách.module.ts.
import { Module } from "@nestjs/common";
import { MongooseModule } from "@nestjs/mongoose";
import { BookService } from './books.service';
import { BookResolver } from './books.resolver';
import { Book, BookSchema } from './book.model';@Module({
providers: [
BookService,
BookResolver
],
imports: [MongooseModule.forFeature([
{
name: Book.name,
schema: BookSchema,
},
]),
],
})
export class BooksModule {}
Làm việc với các đột biến
Trong khi bạn sử dụng truy vấn để truy xuất dữ liệu trong GraphQL, các đột biến sẽ tạo hoặc cập nhật dữ liệu trong cơ sở dữ liệu. Để tạo đột biến, bạn cần chấp nhận dữ liệu từ người dùng. Các Kiểu đầu vào trình trang trí, biến một lớp thành loại đầu vào GraphQL, rất hữu ích ở đây.
import { InputType, Field } from '@nestjs/graphql';@InputType()
export class BookInput {
@Field()
title: string;
@Field()
author: string;
@Field()
publishedDate: boolean
}
Bây giờ bạn có thể cập nhật sách.resolver.ts để trông như thế này:
import { Resolver, Query, Mutation, Args, ID } from '@nestjs/graphql';
import { Book } from './book.model';
import { BookService } from './books.service';
import { BookInput } from './book.input';@Resolver(() => Book)
export class BookResolver {
constructor(private readonly bookService: BookService) { }
@Mutation(() => Book)
async createBook(@Args('input') input: BookInput): Promise<Book> {
return this.bookService.create(input);
}
@Mutation(() => Book)
async updateBook(
@Args('id', { type: () => ID }) id: string,
@Args('input') input: BookInput,
): Promise<Book> {
return this.bookService.update(id, input);
}
@Mutation(() => Book)
async deleteBook(@Args('id', { type: () => ID }) id: string): Promise<Book> {
return this.bookService.delete(id);
}
}
Và sách.service.ts như thế này:
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { Book, BookDocument } from './book.model';@Injectable()
export class BookService {
constructor(@InjectModel(Book.name) private bookModel: Model<BookDocument>) { }
async create(book: Book): Promise<Book> {
const newBook = new this.bookModel(book);
return newBook.save();
}
async update(id: string, book: Book): Promise<Book> {
return this.bookModel.findByIdAndUpdate(id, book, { new: true }).exec();
}
async delete(id: string): Promise<Book> {
return this.bookModel.findByIdAndDelete(id).exec();
}
}
Các @Đột biến trình trang trí đánh dấu một chức năng là một loại đột biến và @Args trình trang trí lấy bất kỳ đầu vào nào được truyền vào hàm.
Cuối cùng, bạn nên nhập khẩu SáchMô-đun vào trong Mô-đun ứng dụng để làm cho nó hoạt động. Bạn cũng nên vượt qua SáchMô-đun ĐẾN forRootAsync như được thấy bên dưới.
import { BooksModule } from './books/books.module';
* other imports
*/@Module({
imports: [
ConfigModule.forRoot({
load: [mongodbConfig],
isGlobal: true
}),
NestGraphQLModule.forRootAsync<ApolloDriverConfig>({
driver: ApolloDriver,
inject: [ConfigService],
useFactory: async (configService: ConfigService) => ({
autoSchemaFile: join(process.cwd(), 'src/schema.gql'),
installSubscriptionHandlers: true,
sortSchema: true,
playground: true,
debug: configService.get<boolean>("DEBUG"),
uploads: false,
}),
}),
MongooseModule.forRootAsync({
inject: [ConfigService],
useFactory: async (configService: ConfigService) => ({
uri: configService.get('MONGO_URI')
})
}),
BooksModule,
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
Bạn có thể kiểm tra mã bằng cách chạy bắt đầu chạy npm: dev trong thiết bị đầu cuối của bạn và ứng dụng của bạn sẽ bắt đầu thành công trên cổng 3000.
Mở localhost:3000/graphql trong trình duyệt của bạn để hiển thị Graphiql giao diện nơi bạn có thể kiểm tra các truy vấn và đột biến. Đây là một ví dụ hiển thị một truy vấn:
Và đây là một ví dụ về đột biến:
Xây dựng API hiệu quả với NestJS và GraphQL
Xây dựng API GraphQL trong NestJS với MongoDB bằng Mongoose liên quan đến việc xác định lược đồ cho API GraphQL, lược đồ cho mô hình Mongoose, dịch vụ để tương tác với cơ sở dữ liệu và trình phân giải để ánh xạ các hoạt động của GraphQL sang các phương thức dịch vụ.
NestJS có chức năng tích hợp sẵn để xây dựng API, bao gồm trình trang trí để xác định tuyến đường, trình bảo vệ để bảo vệ chúng và phần mềm trung gian để xử lý các yêu cầu và phản hồi. Nó cũng hỗ trợ các cơ sở dữ liệu khác như PostgreSQL, MySQL và SQLite, cũng như các thư viện GraphQL khác như Apollo và TypeGraphQL.