DEV Community

Cover image for GraphQL in NestJS: A Concise 5-Minute Guide
Subham
Subham

Posted on • Edited on

GraphQL in NestJS: A Concise 5-Minute Guide

🔥Connect: https://www.subham.online

🔥Twitter: https://twitter.com/TheSubhamMaity


This guide will help you set up GraphQL in your NestJS application. It will cover the installation, configuration, and basic usage of GraphQL with NestJS.

Why GraphQL over REST?

In traditional REST APIs, you might end up over-fetching or under-fetching data. Over-fetching is when the client downloads more information than is actually needed in the app. Under-fetching is when a specific endpoint doesn’t provide enough of the required information. The client will need to make additional requests to fetch everything it needs. But with GraphQL, you can ask for exactly what you need and get just that. This makes GraphQL efficient.

Repo Link: https://github.com/Subham-Maity/scalable_server_architecture/tree/main/example/2.%20graphql_typeorm/schema-first-approach

Approach : Schema First Approach

  • This article is based on schema first approach you can check this one for Code First Approach

Installation

  • Install the required dependencies using npm:
npm install @nestjs/graphql @nestjs/apollo @apollo/server graphql
Enter fullscreen mode Exit fullscreen mode

These packages are necessary to set up a GraphQL server. @nestjs/graphql is a NestJS module for GraphQL, @nestjs/apollo is a NestJS module for Apollo, @apollo/server is a community-driven, open-source GraphQL server, and graphql is the JavaScript reference implementation for GraphQL.

Configuration

  1. Import GraphQLModule
  • Open the app.module.ts file and import the GraphQLModule.
import { ApolloDriverConfig, ApolloDriver } from '@nestjs/apollo';
import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { BookResolver } from './book/book.resolver';

@Module({
  imports: [
    GraphQLModule.forRoot<ApolloDriverConfig>({
      driver: ApolloDriver,
      playground: true, // Set to false in production. It enables the GraphQL Playground where you can test your queries.
      typePaths: ['./**/*.graphql'], // Specify the location of GraphQL files. It tells the server where to find our type definitions.
    }),
    BookResolver, // Import the resolver. Resolvers handle the incoming GraphQL queries.
  ],
  controllers: [],
  providers: [],
})
export class AppModule {}
Enter fullscreen mode Exit fullscreen mode

Usage

Follow these steps to create a basic GraphQL module, resolver, and schema:

  1. Create a Module
  • Create a new module for your GraphQL entities (e.g., book.module.ts).
import { Module } from '@nestjs/common';
import { BookResolver } from './book.resolver';

@Module({
  imports: [],
  controllers: [],
  providers: [BookResolver], // Import the resolver. Resolvers are responsible for defining how the fields in the schema are populated.
})
export class BookModule {}
Enter fullscreen mode Exit fullscreen mode
  1. Create a Resolver
  • Create a new resolver for your GraphQL queries and mutations (e.g., book.resolver.ts).
import { Query, Resolver } from '@nestjs/graphql';

@Resolver('Book')
export class BookResolver {
  @Query('books')
  getAllBooks() {
    return [
      {
        id: 1,
        title: 'Book 1',
        author: 'Author 1',
        price: 10,
      },
      {
        id: 2,
        title: 'Book 2',
        author: 'Author 2',
        price: 20,
      },
      {
        id: 3,
        title: 'Book 3',
        author: 'Author 3',
        price: 30,
      },
    ];
  }
}
Enter fullscreen mode Exit fullscreen mode

In the above code, @Resolver('Book') is a decorator that defines Book as a GraphQL object type, and @Query('books') is a decorator that defines a GraphQL query to fetch all books.

  1. Create a GraphQL Schema
  • Create a new GraphQL schema file (e.g., book.schema.graphql).
type Book {
  id: ID!
  title: String!
  price: Int!
}

type Query {
  books: [Book]
}

type Mutation {
  addBook(title: String!, price: Int!): Book
}
Enter fullscreen mode Exit fullscreen mode

This schema defines a Book type, a query to fetch all books, and a mutation to add a new book.

Testing

  1. Start the NestJS Server
  • Run the NestJS server and navigate to http://localhost:3000/graphql.
  1. Open the GraphQL Playground
  • You should see the GraphQL Playground interface.
  1. Execute a Query
  • Enter the following query in the playground:
{
  books {
    price
    title
  }
}
Enter fullscreen mode Exit fullscreen mode
  1. View the Result
  • Click the "Play" button, and you should see the following result:
{
  "data": {
    "books": [
      {
        "price": 10,
        "title": "Book 1"
      },
      {
        "price": 20,
        "title": "Book 2"
      },
      {
        "price": 30,
        "title": "Book 3"
      }
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode

This guide covers the basic setup and usage of GraphQL with NestJS. You can extend this example by adding more complex types, queries, and mutations based on your application's requirements.

Compare (Optional)

let's compare the syntax for CRUD operations in REST with Mongoose/Prisma and GraphQL:

  1. Create (POST in REST)
  • REST with Mongoose:
app.post('/books', async (req, res) => {
  const book = new Book(req.body);
  await book.save();
  res.status(201).send(book);
});
Enter fullscreen mode Exit fullscreen mode
  • GraphQL:
mutation {
  createBook(title: "New Book", author: "Author Name") {
    id
    title
    author
  }
}
Enter fullscreen mode Exit fullscreen mode
  1. Read (GET in REST)
  • REST with Mongoose:
app.get('/books', async (req, res) => {
  const books = await Book.find({});
  res.send(books);
});
Enter fullscreen mode Exit fullscreen mode
  • GraphQL:
query {
  books {
    id
    title
    author
  }
}
Enter fullscreen mode Exit fullscreen mode
  1. Update (PUT in REST)
  • REST with Mongoose:
app.put('/books/:id', async (req, res) => {
  const book = await Book.findByIdAndUpdate(req.params.id, req.body, { new: true });
  res.send(book);
});
Enter fullscreen mode Exit fullscreen mode
  • GraphQL:
mutation {
  updateBook(id: "1", title: "Updated Book") {
    id
    title
    author
  }
}
Enter fullscreen mode Exit fullscreen mode
  1. Delete (DELETE in REST)
  • REST with Mongoose:
app.delete('/books/:id', async (req, res) => {
  const book = await Book.findByIdAndDelete(req.params.id);
  res.send(book);
});
Enter fullscreen mode Exit fullscreen mode
  • GraphQL:
mutation {
  deleteBook(id: "1") {
    id
    title
    author
  }
}
Enter fullscreen mode Exit fullscreen mode
  1. Read a Single Item (GET in REST)
  • REST with Mongoose:
app.get('/books/:id', async (req, res) => {
  const book = await Book.findById(req.params.id);
  res.send(book);
});
Enter fullscreen mode Exit fullscreen mode
  • GraphQL:
query {
  book(id: "1") {
    id
    title
    author
  }
}
Enter fullscreen mode Exit fullscreen mode

In GraphQL, you can see that the operations are more concise and we can specify exactly what data we want to get back, which can lead to performance improvements. In REST, the server determines what data is sent back in each request, which can lead to over-fetching or under-fetching of data. However, REST can be simpler to use for simple APIs and doesn't require a schema definition like GraphQL does. Both have their uses depending on the situation.

Top comments (1)

Collapse
 
andrew_k_690ae9c09973e864 profile image
Andrew K

It seems you mixed up "code-first-approach" and "schema-first-approach" in your repository.