Menggunakan NestJS dan MongoDB untuk Membangun API GraphQL
Table of content:
GraphQL dan NestJS membuat kemitraan yang sangat baik, memberi Anda dasar yang kuat untuk API Anda dan kerangka kerja yang mudah digunakan untuk membangun aplikasi web yang dapat diskalakan. Kombinasi ini sempurna untuk membuat aplikasi siap produksi, dan keduanya merupakan alat yang sangat relevan dalam ekosistem teknologi saat ini.
Cari tahu lebih lanjut tentang cara membuat API menggunakan kedua produk.
Apa itu GraphQL?
GraphQL adalah bahasa kueri dan manipulasi data yang dapat Anda gunakan untuk membangun API dengan cara yang lebih tepat dan ringkas. GraphQL memberikan deskripsi lengkap dan memadai tentang data yang ada di API dan memberikan kekuatan kepada klien untuk mendapatkan data yang tepat yang dibutuhkan.
GraphQL menyediakan banyak fitur yang tidak dimiliki REST API, mulai dari kueri data yang akurat hingga alat pengembang yang lebih baik, seperti graphiql editor. Ini juga memungkinkan Anda untuk meminta banyak sumber daya melalui satu permintaan.
Apa itu NestJS?
NestJS adalah kerangka kerja Node.js progresif yang dapat Anda gunakan untuk membangun aplikasi sisi server yang dapat diskalakan dan efisien. NestJS menyediakan banyak plugin, di samping alat untuk pengembangan yang cepat dan mudah termasuk dukungan GraphQL, GRPC, WebSockets, dll.
NestJS terkenal di ekosistem karena struktur proyeknya yang dioptimalkan menggunakan modul, pengontrol, layanan, dan skema. CLI bawaannya memungkinkan Anda membuat arsitektur API terstruktur. Anda dapat menggunakan prinsip injeksi ketergantungan untuk mengontrol bagaimana bagian aplikasi berkomunikasi satu sama lain.
Menerapkan GraphQL Dengan NestJS dan MongoDB
Sebelum membuat API dengan NestJS dan GraphQL, Anda harus memiliki dependensi yang tepat. Anda perlu menginstal Node.js dan NestJS, yang dapat Anda instal dengan menjalankannya npm i -g @nestjs/cli.
Contoh berikut adalah aplikasi sederhana yang menyimpan info tentang buku. Jalankan perintah berikut di terminal Anda untuk membuat aplikasi NestJS baru:
nest new <app-name>
Arahkan ke direktori aplikasi yang dihasilkan (
$ npm install --save @nestjs/config @nestjs/graphql graphql-tools graphql \
@nestjs/apollo apollo-server-express @nestjs/mongoose @types/graphql
Ada dua pendekatan utama untuk membangun API GraphQL, yaitu:
- Pendekatan skema-pertama: di mana Anda mendeskripsikan API dalam file definisi skema atau SDL, dan NestJS menghasilkan definisi TypeScript berdasarkan pada mereka.
- Pendekatan kode pertama: di mana Anda menentukan kueri, mutasi, dan fungsionalitas GraphQL lainnya menggunakan kelas dan dekorator TypeScript, dan NestJS menghasilkan file SDL berdasarkan pada mereka.
Contoh berikut menjelaskan cara menggunakan pendekatan code-first.
Pertama, Anda perlu menginisialisasi GraphQL di file AppModule dan hubungkan ke database 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 {}
Modul ini mengimpor file Modul GraphQL dari @nestjs/graphql dan MongooseModule dari @nestjs/mongoose yang membantu terhubung ke MongoDB. Itu AutoSchemaFile properti menentukan lokasi file skema yang dihasilkan, dan sortSchema properti memastikan bahwa ia mengurutkan bidang menurut abjad.
Inilah yang MongoDB Anda config file akan terlihat seperti:
import { registerAs } from '@nestjs/config';
* Mongo database connection config
*/
export default registerAs('mongodb', () => {
const {
MONGO_URI
} = process.env;
return {
uri: `${MONGO_URI}`,
};
});
Mendefinisikan Skema GraphQL
Setelah menyiapkan koneksi GraphQL dan MongoDB, Anda harus menentukan kueri dan mutasi GraphQL untuk menghasilkan skema (skema.gql) berkas.
Menulis Pertanyaan
Dalam pendekatan kode pertamaAnda membuat model menggunakan Tipe Objek penghias. Anda nantinya akan mengubah model ini menjadi tipe GraphQL.
Contohnya:
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);
GraphQL, secara default, tidak dapat menggunakan skema yang dibuat. Untuk membuatnya berfungsi, Anda memerlukan layanan penyelesai yang berisi fungsi untuk mengeksekusi tipe GraphQL. Anda dapat melakukannya dengan Penyelesai penghias.
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);
}
}
Anda dapat menerapkan Layanan Buku, diimpor di atas, sebagai berikut:
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();
}
}
Anda juga perlu menambahkan BookResolver ke daftar penyedia di buku.modul.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 {}
Bekerja Dengan Mutasi
Saat Anda menggunakan kueri untuk mengambil data di GraphQL, mutasi membuat atau memperbarui data di database. Untuk membuat mutasi, Anda perlu menerima data dari pengguna. Itu Tipe masukan dekorator, yang mengubah kelas menjadi tipe input GraphQL, sangat berguna di sini.
import { InputType, Field } from '@nestjs/graphql';@InputType()
export class BookInput {
@Field()
title: string;
@Field()
author: string;
@Field()
publishedDate: boolean
}
Anda sekarang dapat memperbarui buku.penyelesai.ts untuk terlihat seperti ini:
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);
}
}
Dan buku.layanan.ts seperti ini:
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();
}
}
Itu @Mutasi dekorator menandai fungsi sebagai jenis mutasi dan @Args dekorator mengambil input apa pun yang diteruskan ke fungsi.
Terakhir, Anda harus mengimpor file BooksModule ke dalam AppModule untuk membuatnya fungsional. Anda juga harus lulus BooksModule ke untuk RootAsync seperti yang terlihat di bawah ini.
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 {}
Anda dapat menguji kode dengan menjalankan npm jalankan mulai: dev di terminal Anda, dan aplikasi Anda akan mulai dengan sukses di port 3000.
Membuka localhost:3000/graphql di browser Anda untuk menampilkan Graphiql antarmuka tempat Anda dapat menguji kueri dan mutasi. Berikut adalah contoh yang menampilkan kueri:
Dan inilah contoh mutasi:
Bangun API yang Efisien Dengan NestJS dan GraphQL
Membangun API GraphQL di NestJS dengan MongoDB menggunakan Mongoose melibatkan pendefinisian skema untuk API GraphQL, skema untuk model Mongoose, layanan untuk berinteraksi dengan database, dan penyelesai untuk memetakan operasi GraphQL ke metode layanan.
NestJS memiliki fungsionalitas bawaan untuk membuat API, termasuk dekorator untuk menentukan rute, penjaga untuk melindunginya, dan middleware untuk menangani permintaan dan tanggapan. Ini juga mendukung database lain seperti PostgreSQL, MySQL, dan SQLite, serta perpustakaan GraphQL lainnya seperti Apollo dan TypeGraphQL.