Before starting Graphql,we will start with some questions asking :-
Why graphql?
What was the need of graphql when we had SQL languages?
So, what is SQL? SQL is Structured Query Language, originally written for accessing data from databases. There are four basic operations in SQL: SELECT, INSERT, UPDATE and DELETE. The biggest advantage of SQL is, you could “query” for exactly what you need.
For example, if you want to query for all users that have the first name “Anyname” from a SQL database that has a table called Users, you write a query like this:
SELECT * FROM USERS WHERE FirstName=“Anyname”
Now, how would you fetch the same with REST?
There are two options here,
- Define an endpoint on the server-side for fetching users with the fname “Anyname”.
- Define a generic endpoint for fetching all users and filter the list for users with fname “Anyname” on the client-side.
So it’s either, “/userAnyname” or “/users” followed by users.filter(user => user.fname == Anyname)
Do you see a problem? Although we have a powerful language like SQL (of course it has its own drawbacks) and a neat way to talk to SQL from a client using REST, somehow there seems like a disconnect:
- The first approach is clearly not scalable because we can’t define a separate endpoint for each user.
- On the other hand, the second approach is very generic, bandwidth expensive and needs post-processing on the client-side.
REST(not exactly)+SQL=GRAPHQL
Power of SQL and REST gives what we need from the client side.
So what it means is that Graphql is a query language that connects us to the database and gives us what we need to show on the client side.Graphql query gives out the data that we have requested.
So What is Query in this?
- Queries are the call from the server for data to represent on the front.Queries are the strings that are sent on the body of HTTP POST request.Query itself define its type of data it has handled or which type of data query is going to show.We can define the input data type and based on it output.
- For example, the below query is asking the GraphQL server for the fname and age of all the users in the DB.
query {
users {
fname
age
}
}
For the Above query requested, server will respond in the json format having the same structure as we have our query.
RESPONSE:-
data : {
users [
{
"fname": "Joe",
"age": 23
},
{
"fname": "Betty",
"age": 29
}
]
}
The above query will give either response in JSON format which will have data as “key” where as if there has an error then it will return an error in response.
Make sure client side error handling is more important so that user could get the easily understandable error.
Query is a “root type” because it’s a type that maps to operation and operations represent the roots of our Query document.
Mutation
Mutation is the second kind of “root type” which lets us write data to the DB.Mutation includes POST and PUT requests.
- For Example:-
mutation createUser{
addUser(fname: "Marry", age: 19) {
id
}
}
RESPONSE:-
data : {
addUser : "a36e4h"
}
The above mutation is saying that add a user with firstname of Marry and her age is 19 yrs old.It help us to add the user with its arguments and its type define in it.So the above mutation on success will add an user with defined name and age ,else on unsuccessful attempt it will show error.
Subscription
Subscription says that I am listening to what you are updating in realtime.It is another operation for Graphql which helps in updating the content when there is new addition of content in real time.You can understand it by taking newsletter example.As we get daily updates for any subscribed data if there is new addition of data.
Setup
Installation#
Setup your graphql server that will respond to your queries,mutation or subscription.For the server we will use Apollo server.
Apollo Server is an open source implementation of the graphql.
We will set up a new react app and we are taking this as you know the setup procedure for the app.
We will let you know the installation and setup for the server in our app.
mkdir graphql-server-example
> cd graphql-server-example
> npm init -y
This will initialize an empty project with a package.json file for storing the dependencies.
Next, let’s install the GraphQL dependencies.
> npm install apollo-server graphql nodemon
This installs the apollo-server, graphql and nodemon for monitoring changes to the files. Of course, let’s update the scripts key in package.json for nodemon to work.
“scripts”: { “start”: “nodemon -e js, json, graphql }
Database#
For databases we will be having mock data in our server,whereas project have a database server holding.So we will be having trail mock data for further proceeding.
We will put mock data in index.js in the following format:-
export const UserDatabase =[{
email: '[email protected]' ,
role: 'trainee',
},
{
email: '[email protected]' ,
role: 'trainer',
},
{
email: '[email protected]' ,
role: 'head-trainer'
}
]
Rough diagram of how graphql works:-
1st step:-
While we are thinking about creating a server we need to first create our schema.Where as Schema consist of TypeDefs and Resolvers.
Now in your mind a question arises,what are typedefs?,Why do we need TypeDefs.Here is the answer, As we saw earlier While hitting our query on server thorough playground(expecting you have knowledge of using the playground) we defines the query and its types.So TypeDefs are the object that defines the list of types available. Type definitions define the “shape” of your data and specify which ways the data can be fetched from the GraphQL server.
We will create schema.graphql and keep our query,mutation and subscription in it.It will define the input parameters and response will be in type.graphql.
type Query {
getTraineeDetail(email: String!,role:String): traineeResponse,
getUserResponse:showResponse
}
type Mutation {
addTrainee(input:editTable):editData
}
2nd step:-
Define your typedefs in type.graphql file.
type traineeResponse {
message: String
status: Int
data: [User]
}
type User {
email: String
role: String
permissionType: [String]
}
type showResponse {
message: String
status: Int
data: [readData]
}
type readData {
traineeEmail: String
reviewerEmail: String
}
type editEmail {
traineeEmail: String
reviewerEmail: String
}
input editTable {
traineeEmail: String
reviewerEmail: String
}
type editData {
message: String
status: String
data: [editEmail]
}
type Subscription {
listenLikes : [User]
}`;
we define a User type with email, role and likes. We also define the data type of each field as String or Int. GraphQL supports four basic data types: String, Int, Float, Boolean.If you add an exclamation mark after next to the type then it will make it the required field.
We also Define type for Query,Mutation and subscription.
For Type Query:-
When we define a type query for a user it calls the set of objects that has a particular user with id has related information.
Similarly from the above example we have another type query which calls posts with id,user and body.The result will be a set of objects which has posts related information.
type Query {
getTraineeDetail(email: String!,role:String): traineeResponse,
getUserResponse:showResponse
}
For Type Mutation:-
For type mutation it’s like an update to the data,which means when we have type mutation we are adding some data to the database.Also, you can understand this from inserting data by taking parameters i.e fname and output as list of users.
type Mutation {
addTrainee(input:editTable):editData
}
For Type Subscription:-
For type subscription it’s listen the updation in data.It return updated data.
type Subscription {
listenLikes : [User]
}
Now we have typedefs for the query.We will work on logic for the server so that it knows how to respond to clients.
3rd step:-
Resolvers
const Query = {
getTraineeDetail: async (_, {
email,
role,
}, {}) => {
try {
if (!email && !role) {
throw new Error("Please fill the blank Input");
}
if (!validateEmail(email)) {
throw new Error("Invalid Email,please check your email must exist with successive.tech");
}
validateRole(email, role);
const permission = await getPermission(role)
return {
message: "success",
status: 200,
data: [{
email: email,
role: role,
permissionType: permission,
}]
};
} catch (error) {
return error;
}
},
getUserResponse: async (_, {}, {}) => {
try {
return {
message: "success",
status: 200,
data: User
}
} catch (error) {
return error;
}
}
}
Subscription: {
listenLikes: {
subscribe: () => pubsub.asyncIterator(['LIKES'])
}
}
Above resolver will be easily understood if you have basic knowledge of js.
We have used the new term here PUBSUB.Now what is PubSub?
Real time communication system using web sockets. The best part is, everything about web sockets is abstracted away and it is simple and easy to use.
Now we have typDefs and resolver functions are ready .we are good to go to use server,our server is ready.We have apollo server so it provides its playground to hit queries.
Start the server with npm start command and it will play at http://localhost:4000/ .You will get the picture of the playground as below.
That’s it our server is working like a star.We can see our query and its responses.
Conclusion:
The most important part for a blog is the conclusion that we have good points and bad points while using graphql.
-Easy to use.
-Easy implementation
-Exact data extraction
-One request,many access
-Very much compatible
-Field level depreciation
References:-