1
votes

I have implementation of Post Comment models in Apollo graphql which schema is and I want to know which implementation is correct?

  type Post {
    id: ID!
    title: String
    image: File
    imagePublicId: String
    comments: [Comment] # we have type for Comment in another schema file
    createdAt: String
    updatedAt: String
  }

  extend type Query {
    # Gets post by id
    getPosts(authUserId: ID!, skip: Int, limit: Int): Post
  }

and I have resolver which resolves Post type and resolves comment by help of populate function of mongoose as bellow:

const Query = {
getPosts: async (root, { authUserId, skip, limit }, { Post }) => {

    const allPosts = await Post.find(query)
      .populate({
        path: 'comments',
        options: { sort: { createdAt: 'desc' } },
        populate: { path: 'author' },
      })
      .skip(skip)
      .limit(limit)
      .sort({ createdAt: 'desc' });

    return allPosts
  }
}

the second way possible way of implementing getPosts query in resolver is by not using populate function of mongoose and resolve it manually by writing a separate function for it:

const Query = {
getPosts: async (root, { authUserId, skip, limit }, { Post }) => {
    const allPosts = await Post.find(query)
      .skip(skip)
      .limit(limit)
      .sort({ createdAt: 'desc' });

    return allPosts
  }
  Post: {
   comments: (root, args, ctx, info) => {
    return Comment.find({post: root._id}).exec()
   }
  }
}
1
You don't want to populate, because what about if you don't ask for the populated data? You are still querying for it & holding that data in memory. Do all your population in a separate resolver. The second solution is the bestDanStarns

1 Answers

2
votes

It depends.

A resolver is only fired if its field is requested. So if the getPosts resolver fetches the posts without comments, and the comments resolver fetches the comments for each post, the comments will only be fetched if the comments field is included in the request. This can improve the performance of such requests by preventing overfetching on the backend.

On the other hand, by individually querying the comments for each post, you're drastically increasing the number of requests to your database (the n+1 problem). We can avoid this issue by fetching all the posts and all the comments in one query, but, again, we might not necessarily need the comments at all.

There's two options for resolving this dilemma:

  1. Fetch the comments inside the comments resolver, but use dataloader to batch the database requests. This way you're making 2 database requests instead of n + 1 many.

  2. Parse the GraphQLResolveInfo object passed as the fourth parameter to your resolver to determine whether the comments field was requested. This way, you can conditionally add the populate call only if the comments field was actually requested.