What is GraphQL
As per the documentation, "GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data. GraphQL provides a complete and understandable description of the data in your API, gives clients the power to ask for exactly what they need and nothing more, makes it easier to evolve APIs over time, and enables powerful developer tools."
But why GraphQL?
Imagine a scenario where the client needs user data but only a username list should be the output. The next one is where the client needs only the user's phone number and the requirement list goes on. Now in the situations mentioned above would you like to write different APIs or send the whole user's data (unnecessary/extra data) over network calls?
This is where GraphQL comes into the picture by using GraphQL queries you can do db actions/queries and return the output directly
Now let's dive into the implementation part, I am going to use the Apollo server to set up Graphql
npm i @apollo/server body-parser express axios
I have set up async startServer function which includes declaring and starting the server, and app.use indicates that any query for the URL /graphql is going to be handled by the server(Apollo)
const server = require("express")
const bodyParser = require("body-parser")
const { ApolloServer} = require("@apollo/server")
const axios = require("axios")
const { expressMiddleware } = require("@apollo/server/express4")
const cors = require("cors")
var app = server()
const startServer = async () => {
app.use(cors())
app.use(bodyParser.json())
const server = new ApolloServer({})
await server.start()
app.use(
"/graphql",
expressMiddleware(server)
)
app.listen(8000, () => {
console.log("port started on 8000")
})
}
startServer()
but the Apollo server has certain restrictions where typeDefs and resolvers are compulsory for the server to start. Now let's see what are typeDefs and resolvers
typeDefs are nothing but schema along with type declarations
Example
type Post{
id:ID (ID denotes id field can be of type anything)
title:String! (! Dentos that field can not be null )
body:String
}
resolvers are the ones that give out the result for the queries made.
Let's take up a dummy example for a deeper understanding, user and todo are two different schemas where each user can have multiple todos, and every todo is linked to a particular user by userId.Time to declare some typeDefs.
const server = new ApolloServer({
typeDefs: `
type User{
name: String!
}
type Todo{
id: ID!
title: String!
}
type Query{
getTodos:[Todo]
getUsers:[User]
}`,
resolvers:{
Query: {
getTodos: async () => (await
axios.get("https://jsonplaceholder.typicode.com/todos")).data,
getUsers: async () => (await
axios.get("https://jsonplaceholder.typicode.com/users")).data,
}
})
type Query indicates the query function name and the data return format, so now in the resolvers also Query should be declared and the action to take place inside the function being called should be written.
getTodos is going to fetch all the todo lists in the array format and getUsers is going to fetch all the users in array format as declared in type Query.
Run your server on http://localhost:8000/graphql below mentioned UI will be given by Apollo only,in getTodos query I have mentioned the fields that I want to be in the output but you cannot send any random field, the field being requested should be declared in the schema:
Now let's make the query a little more complex
I want to get all the todos along with the user name who has created it
change the schema and resolvers accordingly
type Todo{
id:ID!
title:String!
user:User
userId:String!
}
resolvers{
Todo: {
user: async (todo) => (await axios.get(`https://jsonplaceholder.typicode.com/users/${todo.userId}`)).data
},
Query:{remains the same}
}
The Todo in the resolvers indicates that whenever there is a query Todo needs to get the user details to whom the todo belongs based on userId meanwhile in the schema I have added a user field that will hold the User details which refers to the User schema which is already declared.
Challenege
Write a function to fetch only particular todo based on the id field. Let me know the query and resolver functions in the comments below.
Conclusion
As we saw what is graphql, why there is a need for it, and a simple example of graphql query in the upcoming blog I will be explaining about mutations i.e. updation/deletion/creation.
Top comments (0)