Getting Started with GraphQL - Nodejs
Tags: graphql, query, node, javascript
Published: 2023-11-22 06:04:25

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ktqzgtygvovdydx8plft.png)

**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:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/brecyndpdzqplosj8u18.png)

getUsers:
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gv71s54ecb8pcridlx5e.png)

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.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ealrv6ce4kcw72sl4ws5.png)

**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.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3buo96tjesgmbolmzj6h.gif)