使用 Apollo Graphql Server 解析关系文档

Resolving relational document using Apollo Graphql Server

我在 Apollo graphql 中实施了 Post 评论模型,我想知道哪个实施是正确的?

  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
  }

我有一个解析器,它解析 Post 类型,并借助 mongoose 的填充函数解析注释,如下所示:

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
  }
}

在解析器中实现 getPosts 查询的第二种方法可能的方法是不使用 mongoose 的填充函数,并通过为它:

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()
   }
  }
}

视情况而定。

解析器只有在其字段被请求时才会被触发。因此,如果 getPosts 解析器获取没有评论的 post,而 comments 解析器获取每个 post 的评论,评论将 仅 [=如果 comments 字段包含在请求中,则获取 35=]。这可以通过防止后端过度获取来提高此类请求的性能。

另一方面,通过单独查询每个 post 的评论,您将大大增加对数据库的请求数量 (the n+1 problem)。我们可以通过在一个查询中获取所有 post 和所有评论来避免这个问题,但是,同样,我们可能根本不需要评论。

解决这个难题有两种选择:

  1. 获取 comments 解析器中的注释,但使用 dataloader 对数据库请求进行批处理。这样你就可以发出 2 个数据库请求,而不是 n + 1 个。

  2. 解析作为第四个参数传递给解析器的 GraphQLResolveInfo 对象,以确定是否请求了 comments 字段。这样,您可以有条件地添加 populate 调用,仅当实际请求了 comments 字段时。