1

How can I do multiple nested query using GraphQL Yoga?

This is my data

{
  "user": [{
      "id": 1,
      "name": "Thomas",
      "comment_id": [1, 2, 3]
    },
    {
      "id": 2,
      "name": "Riza",
      "comment_id": [4, 5, 6]
    }
  ],
  "comment": [{
      "id": 1,
      "body": "comment 1"
    },
    {
      "id": 2,
      "body": "comment 2"
    },
    {
      "id": 3,
      "body": "comment 3"
    }
  ]
}

The scenario is that I want to query a particular user with all its comments, but the user only stores the comment ids.

This is my code

const { GraphQLServer } = require('graphql-yoga');
const axios = require('axios');

const typeDefs = `
  type Query {
    user(id: Int!): User
    comment(id: Int!): Comment
  }

  type User {
    id: Int
    name: String
    comment: [Comment]
  }

  type Comment {
    id: Int
    body: String
  }
`;

const resolvers = {
  Query: {
    user(parent, args) {
      return axios
        .get(`http://localhost:3000/user/${args.id}`)
        .then(res => res.data)
        .catch(err => console.log(err));
    },
    comment(parent, args) {
      return axios
        .get(`http://localhost:3000/comment/${args.id}`)
        .then(res => res.data)
        .catch(err => console.log(err));
    },
  },
  User: {
    comment: parent =>
      axios
        .get(`http://localhost:3000/comment/${parent.comment_id}`)
        .then(res => res.data)
        .catch(err => console.log(err)),
  },
};

const server = new GraphQLServer({ typeDefs, resolvers });
server.start(() => console.log('Server is running on localhost:4000'));

Desired Query

{
  user(id: 1) {
    id
    name
    comment {
      id
      body
    }
  }
}

But it returns not found, because the endpoint that the axios hit is http://localhost:3000/comment/1,2,3'

How can i make it return all user's comments? Thanks guys!

Riza S
  • 85
  • 1
  • 1
  • 7

2 Answers2

1

Assuming that comments API /comment/:id accepts only single id, you would need to make one API call per comment ID (unless there is an API which takes multiple ID's and return their data) and then return response from comment field resolver of User type.

This is how resolver for comment field would look like in that case:

User: {
    comment: parent => {
        let results = await Promise.all(parent.comment_id.map((id) => axios.get(`http://localhost:3000/comment/${id}`))) 
        return results.map((result) => result.data)
     }
  }

Raeesaa
  • 3,267
  • 2
  • 22
  • 44
  • Oh wow it's working! Thank you for your help! And yep, the comments API only accepts single ID. I also found another solution, which one do you think it's better? Thanks! – Riza S Apr 02 '19 at 02:15
0

Apparently I also found this other solution

User: {
    comment: parent =>
      parent.comment_id.map(id =>
        axios.get(`http://localhost:3000/comment/${id}`).then(res => res.data)
      ),
  },

Performance wise, which one do you think it's better?

Riza S
  • 85
  • 1
  • 1
  • 7