Nested resolvers and relational data in GraphQL
In this tutorial, we are going to learn about how to create relational data and nested resolvers in graphql.
Note: If you don’t know about GraphQL then refer to my previous tutorial GraphQL intro for the beginners
Relational data means consider we have a ‘todo app’ with users and todos where each todo is created by the particular user.
let todos = [
{
id: 1,
title: "This is my todo",
body: "sample content in id 1",
userId: 1
},
{
id: 2,
title: "This is my second todo",
body: "sample content in id 2",
userId: 1
},
{
id: 3,
title: "This is my third todo",
body: "sample content in id 3",
userId: 2
}
]
let users = [
{
id: 1,
name: "sai"
},
{
id: 2,
name: "gowtham"
},
]
if any user asks for their todos we only show the todos created by them using some type of relationship between the user
and todos
.
Let’s start writing code.
Type definitions
type Todo{
id: ID!
title: String!
body: String!
}
type User{
id:ID!
name:String!
}
type Query{
user(id:ID!): User!
}
We created two object types which are Todo
& User
and One Query Type.
Resolvers
Next, we need to tell the graphql how to resolve the user
field in the query.
const resolvers = {
Query: {
user(parent, args, ctx, info) {
if (!args.id) {
throw new Error('id is required')
}
return users.find(user => user.id === +args.id)
}
}
}
Let’s test it now by using the graphql play-ground.
Relational data
In this step, we are creating a relationship between the user and todos for this we need to add
a new field called todos
to the User
type.
type User{
id:ID!
name:String!
todos:[Todo!]!
}
if you ask for a todos
you will get an array of todos where it’s shape should look like Todo
type but we don’t have any resolver for the todos
field.
Nested Resolvers
Let’s create a nested resolver to handle the todos
field.
const resolvers = {
Query: {
user(parent, args, ctx, info) {
if (!args.id) {
throw new Error('id is required')
}
return users.find(user => user.id === +args.id)
}
},
User: {
todos(parent, args, ctx, info) {
//parent is the root object (User is the parent here)
return todos.filter(todo => todo.userId === parent.id)
}
}
}
In the above code, we have added Nested todos
resolver on the User object so that if any user asks for there todos
we need to take the id
from it’s parent and return their todos.
Note: Nested resolvers only run when we query for that nested field otherwise it doesn’t run.