Javascript 使用Apollo Graphql服务器解析关系文档

Javascript 使用Apollo Graphql服务器解析关系文档,javascript,mongoose,graphql,apollo,apollo-server,Javascript,Mongoose,Graphql,Apollo,Apollo Server,我在Apollo graphql中实现了Post-Comment模型,我想知道哪个模式是正确的 type Post { id: ID! title: String image: File imagePublicId: String comments: [Comment] # we have type for Comment in another schema file createdAt: String updatedAt: Strin

我在Apollo graphql中实现了Post-Comment模型,我想知道哪个模式是正确的

  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
  }

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

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的populate函数,并通过为其编写单独的函数手动进行解析:

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
resolver获取没有注释的帖子,而
comments
resolver获取每个帖子的注释,那么只有在请求中包含
comments
字段时,才会获取注释。这可以通过防止后端的过度抓取来提高此类请求的性能

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

解决这一困境有两种选择:

  • 获取
    comments
    resolver中的注释,但用于批处理数据库请求。这样,您将发出2个数据库请求,而不是n+1个请求

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


  • 您不想填充,因为如果您不要求填充的数据呢?您仍在查询它&将该数据保存在内存中。在单独的解析程序中执行所有填充。第二种解决方案是最好的