Recently, GraphQL has made a lot of buzz among the developers community, and it has been seeing a lot of attention because of the dynamicness and lot less redundant data fetching capabilities it packs under its hood. In this Code Tutorial, we will get to learn about:
- what GraphQL really is, why has it created such a hype amongst new age developers?
- How is it different from the REST approach, and finally
- We will be building our own API with GraphQL along with Code Tutorials.
So let's get into it šØš»āš»
#1. What is GraphQL? A quick primer
Before understanding what GraphQL is, letās first understand what Query Languages are. Query Languages are languages that request the data from a database (called queries) to a client side application through a server. A well known example is Structured Query Language, or SQL.
Coming to GraphQL, by definition -
āGraphQL is an open-source data query and manipulation language for APIs, and a runtime for fulfilling queries with existing dataā (source: wiki).
But the question remains the same. What exactly is GraphQL? Simply put, GraphQL is a new age Query Language developed by Facebook that helps Application Programming Interfaces (APIs) fetch only that data which is request by the client, and nothing else, thus enormously reducing the redundant data at the API endpoint and making the requests blazing fast and developer friendly.
But, wasnāt that already being done by RESTful APIs š¤? The answer is yes, but GraphQL is different (and also advantageous) than REST in a lot of ways.
- GraphQL is Client-Driven, whereas REST is Server Driven.
- Queries are organized in terms of Schema and strict typecasting in GraphQL, whereas REST has Endpoints for that task.
- GraphQL calls Specific data with single call. REST calls Fixed data with multiple calls.
- Instead of the GET, POST, PUT, DELETE operations in REST, GraphQL has Query, Mutation and Subscription for data manipulation.
Now that we know the āWhatās and āWhereās of GraphQL, letās dive straight into our favorite part. The Development š¤.
#2. Letās Play with GraphQL
In this section, we will learn about a step-by-step procedure of building an API using GraphQL and Express on top of Node.js. In the next section, we will be implementing these prerequisites into code and start our development for the API.
Prerequisites:
- Understanding of GraphQL
- Node Package Manager (or NPM) with version 10+
- Knowledge of basic querying and server-side programming.
We will be needing a Database to store the user data and everything else that a client side application can request for. For this, we will be using š LowDB, which is a simple file-based JSON database for small projects in the localhost. Then we will be needing a middleware to connect our database system to the requesting frontend application. For this, we will be using the Express middleware with the GraphQL implementation of Express - the graphql-express library. Finally, we will be making a client side application using React which can request all the data from the local database and can perform operations on the database like Read, Write and Delete.
So our roadmap is pretty simple and straightforward š£ļø.
Create a Database Schema > Use a middleware server to query the database > Create a frontend application to use the data.
If this is too much at once for you, do not worry as this is article is being written kept in mind that the reader is a first timer for GraphQL and basic querying as usual.
With that being done, letās dive into the CODE
.
#3. Setting up Express GraphQL
Letās begin with the basic project structure of a Node.js application. Begin a new project in a new folder.
$ mkdir graphql-example
$ cd graphql-example
Use NPM to intiialize a project
$ npm init -y
Install the required dependencies for Express, MongoDB (Mongoose) and some additional dependencies required for the function of Express.
$ npm install express mongoose body-parser cors --save
Apollo Server is a community-maintained open-source GraphQL server that works with all Node.js HTTP server frameworks, so next we are going to download and save that.
$ npm install apollo-server-express --save
This shouldāve created a package.json and a package-lock.json file within your folder. These files contains the information regarding our environment, the dependencies and the specific versions to run those dependencies.
This means our environment is ready and we can now start developing the integrated server and API. We are going to write the Schema inside the index.js file.
In the index.js
file, start off by writing this code.
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}`));
In line number 1 to 6, weāre implementing the necessary modules. Note that here we have imported the ./schema, but we havenāt created that yet. We will be doing this in the next step.
In line number 9 to 14, we are connecting the project to the mongoDB database and logging any error we face to the console.
In line number 16 to 19, weāre creating a new Apollo Server with
typeDefs
andResolver
. Weāll be defining those in the ./schema later in this tutorial.In line 21 to 26, weāre firing up the Express Server at port 4000, when we can actually be able to interact with what weāre building.
GraphQL has two main principles in order to work: types
and resolvers
. We defined them in Apollo Server. Weāll import them from the file weāll create later.
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};
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.
In lines 4 to 19, weāre basically determining the schema of the database that is going to hold the data of movies. Every movie is going to have a Name and a Producer of type String and a Rating of type Number.
#4. Designing the Schema
So now letās move on to the schema.js
file where weāre going to build our GraphQL API.
Create a new file in the root of the folder by the name of schema.js
and add the following code.
const { gql } = require('apollo-server-express');
const Movie = require('./models/movie').Movies;
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(id: ID!, name: String!, producer: String!, rating: Float): Movie
deleteMovie(id: ID!): Movie
}
`
In this, weāre building the schema. We defined the Movie type which will have an ID, name of the movie and the producer, and a rating of type Float. The ā!ā after the types shows that these field are necessary.
Unlike REST approach of getting different tasks done at different endpoint URLs, GraphQL can create operations in a single endpoint. That is what we have done in line line 11 onwards. The type Query determines the GET operations, and type Mutation determines the modification operations like POST, DELETE, etc. In getMovies, weāre returning a list of all available movies in our database and in getMovie weāre getting the specific movie by the ID of that movie.
Now weāre going to link these with the Mongoose Database queries that are going to perform the actions in the database. And this is done by Resolvers. Resolvers are functions that connects schema fields and types to various backends. It can read, write and delete data from and to anywhere in the database, be it SQL, NoSQL or Graph based database.
Hereās how weāre going to implement Resolvers in our code:
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 {
continue;
}
}
);
}
}
}
module.exports = {typeDefs,resolvers};
This is the basic logic of MongoDB and CRUD application and is not in the scope of explanation of this article since it is majorly focussed on GraphQL. Although the logics are pretty simple and straightforward for anyone to understand so do skim through it once.
With this, weāre done with a basic Movie API which can perform all the CRUD Operations on a database of movies. To test this out, weāre going to fire up our node server and open the browser in http://localhost:4000/graphql which will open up the GraphQL Playground.
$ node index.js
š Server ready at [http://localhost:4000/graphql](http://localhost:4000/graphql)
Once the Playground UI opens up, weāre first going to create a Movie Record for the database since it would be empty initially.
And now letās list out all the movies in the database
So we have successfully created a Movie API where we can perform all the CRUD operations on a single endpoint, as well as ask for just the data that we want resulting in blazing fast API response and a developer friendly return object that makes development fast and super easy.
In the next part, we will be using this API in a React Project, along with a brief summary of what we did.
Till then, you can SUPPORT MY WORK here. hope you enjoyed. Stay Safe y'all
Top comments (0)