A Simple CRUD App Using GraphQL, NodeJS, and MongoDB

A Simple CRUD App Using GraphQL, NodeJS, and MongoDB

A Simple CRUD App Using GraphQL, NodeJS, and MongoDB

In my last article, I gave a global introduction to GraphQL. I compared it with REST, as the two of them tend to do the same work, but there are some differences in term of quality and performance.

So in this article, we’re going to build a simple movie app, where we can show, add, edit, and delete movies. That way we’ll get through the basics of GraphQL, which is the main goal of this article — as I assume everyone reading this has already worked with NodeJS and MongoDB.

Creating Project and Installing Dependencies

First, you create a new project folder on your local disk. For instance, I have named mine graphql-tuto. In your Node command prompt, enter:

cd graphql-tuto
npm install express mongoose body-parser cors --save

Now we have installed Express, Mongoose, body-parser, and CORS. I’m not going to detail this since it’s not the main goal of this tutorial.

npm install apollo-server-express --save

From the Apollo Docs, I found that the “Apollo Server is a community-maintained open-source GraphQL server that works with all Node.js HTTP server frameworks,” such as Express.

So create a file named app.js. Add the following code to it to set up the Apollo Express Server and the MongoDB database.

const express = require('express');
const mongoose = require('mongoose');
const schema = require('./schema');
const bodyParser = require('body-parser');
const cors = require('cors');
const { ApolloServer } = require('apollo-server-express');
const url = "mongodb://localhost:27017/moviesdb";
const connect = mongoose.connect(url, { useNewUrlParser: true });
connect.then((db) => {
      console.log('Connected correctly to server!');
}, (err) => {
      console.log(err);
});
const server = new ApolloServer({
      typeDefs: schema.typeDefs,
      resolvers: schema.resolvers
});
const app = express();
app.use(bodyParser.json());
app.use('*', cors());
server.applyMiddleware({ app });
app.listen({ port: 4000 }, () =>
  console.log(`???? Server ready at http://localhost:4000${server.graphqlPath}`));

GraphQL has two main principles in order to work: types and resolvers. I defined them in Apollo Server. We’ll import them from the file we’ll create later.

Also Read:- Develop RESTful API using Node JS, Express JS

For the time being, let’s create the file models/movie.js that’ll contain the movie-Mongoose model.

const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const movieSchema = new Schema({
    name: {
       type: String,
       required: true
    },
    rating: {
       type: Number,
       required: true
    },
    producer: {
       type: String,
       required: true
   }
}, {
    timestamps: true
});
var Movies = mongoose.model('Movie', movieSchema);
module.exports = {Movies, movieSchema};

Every movie will have a name and a producer of type String and a rating of type Number.

So now we add a new file, schema.js, where we’ll build our GraphQL API.

const { gql } = require('apollo-server-express');
const Movie = require('./models/movie').Movies;

First, we import GraphQL as gql from Apollo Server and our movie-Mongoose model.

GraphQL APIs consist of types and resolvers.

Types are where we define our model or schema of the entity we want to represent (Movie in our example). In type, we also declare our queries (getting the list of movies, for example) and mutations (adding a moviem for example). GraphQL types are limited to ID for IDs, Int for integer numbers, Float for float numbers, String, and Boolean. So in our schema file, we add these lines of code:

const typeDefs = gql `
   type Movie {
     id: ID!
     name: String!
     producer: String!
     rating: Float!
   }
   type Query {
     getMovies: [Movie]
     getMovie(id: ID!): Movie
   }
   type Mutation {
     addMovie(name: String!, producer: String!, rating: Float!): Movie
     updateMovie(name: String!, producer: String!, rating: Float): Movie
     deleteMovie(id: ID!): Movie
   }

We defined the Movie type and, of course, each movie will have an id. We put ! next to types (e.g., String!) to indicate this property is required. In our example, everything is required. In the Query type, we have the queries (GET operations).

And in the Mutation type, we have the other operations that’ll modify or make some changes to our database. In getMovies, we return a list of movies — that’s why we have the brackets, [Movie].

That’s it for the first part of our GraphQL API. Now, we move to link this with Mongoose database queries that’ll directly affect the database. And here’s where the resolvers come in.

const resolvers = {
  Query: {
    getMovies: (parent, args) => {
      return Movie.find({});
    },
    getMovie: (parent, args) => {
      return Movie.findById(args.id);
    }
  },
  Mutation: {
    addMovie: (parent, args) => {
      let Movie = new Movie({
        name: args.name,
        producer: args.producer,
        rating: args.rating,
      });
      return Movie.save();
    },
    updateMovie: (parent, args) => {
      if (!args.id) return;
        return Movie.findOneAndUpdate(
         {
           _id: args.id
         },
         {
           $set: {
             name: args.name,
             producer: args.producer,
             rating: args.rating,
           }
         }, {new: true}, (err, Movie) => {
           if (err) {
             console.log('Something went wrong when updating the movie');
           } else {
           }
         }
      );
    }
  }
}

The queries and mutations we declared in the type definitions are detailed as operations that interact with the database. I assume you are familiar with Mongoose since it’s not the point of this article, which is mainly written for GraphQL.

Now we’re going to test our API in GraphQL Playground. So in your navigator, go to http://localhost:4000/graphql.

Also Read:- How to Develop Progressive Web App With React

Author Biography.

Lokesh Gupta
Lokesh Gupta

Overall 3+ years of experience as a Full Stack Developer with a demonstrated history of working in the information technology and services industry. I enjoy solving complex problems within budget and deadlines putting my skills on PHP, MySQL, Python, Codeigniter, Yii2, Laravel, AngularJS, ReactJS, NodeJS to best use. Through Knowledge of UML & visual modeling, application architecture design & business process modeling. Successfully delivered various projects, based on different technologies across the globe.

News & Blogs

6ec3fae84857a1f5dc59eebcc6c0775e.png

Building a carousel component in React using Hooks

One of the problems in web development today is the entangling of different layers. Not only do w...

2cda7519f703462a0eabd1c2e84e0001.jpg

Why shouldn’t you wait to jump onto Angular 2?

AngularJs is a JavaScript framework and is widely adopted framework in building Single Page Web A...

8b77d9abe1f73f94ea9f0f008ff988a1.jpeg

Difference between Sets vs. Arrays in JavaScript

The Set object type was introduced in the 2015 ECMAScript specification and is ready to be used i...