【问题标题】:Which is the correct resolver function approach?哪种是正确的解析器函数方法?
【发布时间】:2017-11-25 03:52:08
【问题描述】:

我想澄清在 Apollo + GraphQL 中我应该为解析器函数使用哪种方法

让我们假设以下架构:

type Post {
  id: Int
  text: String
  upVotes: Int
}

type Author{
  name: String
  posts: [Post]
}

schema {
  query: Author
}

ApoloGraphql tutorial 建议这样的解析器映射:

{Query:{
    author(_, args) {
      return author.findAll()
          }
    }
},
Author {
   posts: (author) => author.getPosts(),
}

据我所知,关于帖子的每个逻辑,例如get author with posts where the count of post upVotes > args.upVotes,必须在author 方法中处理。这为我们提供了以下解析器映射:

{Query:{
    author(_, args) {
      return author.findAll({
              include:[model: Post]
              where: {//post upVotes > args.upVotes}
                })
             }
},
Author {
   posts: (author) => author.getPosts(),
}

调用author,将首先在一个联合查询中选择具有帖子的作者,其中帖子大于args.upVotes。然后它将再次选择该作者的帖子,因为Author ... getPosts()

从技术上讲,我可以通过删除 Author 来达到相同的结果,因为帖子已经包含在小的 author 方法中。

我有以下问题:

  1. 我需要这份声明吗?在哪些情况下?

    Author { posts: (author) => author.getPosts(), }

  2. 如果没有,那么我如何确定是否请求了帖子字段,以便 我可以使帖子有条件地包含,不仅取决于 参数,还包括请求的字段?

  3. 如果是,哪些帖子将包含最终结果?来自的帖子 include 语句,还是 getPosts()?

【问题讨论】:

    标签: graphql apollo graphql-js react-apollo


    【解决方案1】:

    您在问题中包含的解析器映射无效。我假设您对 Author 类型的意思是这样的:

    Author {
      posts: (author) => author.getPosts(),
    }
    

    只要您的author 查询总是 解析为包含posts 属性的对象数组,那么您认为包含客户没有意义是正确的Author 类型上的 posts 字段的解析器。在这种情况下,您的查询解析器已经填充了所有必要的字段,我们无需执行任何其他操作。

    GraphQL 利用默认解析器查找传递给解析器的父(或根)对象的属性,如果它们与被解析字段的名称匹配,则使用这些属性。因此,如果 GraphQL 正在解析 posts 字段,并且没有 posts 的解析器,则默认情况下它会查看它正在处理的 Author 对象,并且它上面是否有一个名为 posts 的属性,它将字段解析为其值。

    当我们提供自定义解析器时,该解析器会覆盖默认行为。因此,例如,如果您的解析器是:

    posts: () => []
    

    那么 GraphQL 将始终返回一组空的帖子,即使 author.findAll() 返回的对象包含帖子。

    那么您什么时候需要包含posts 的解析器?

    如果您的 author 解析器没有“包含”帖子,但客户请求了该字段。就像您说的那样,问题是在某些情况下,我们可能会进行不必要的额外调用,具体取决于您的 author 解析器是否“包含”这些帖子。您可以通过执行以下操作来解决此问题:

    posts: (author) => {
      if (author.posts) return author.posts
      return author.getPosts()
    }
    // or more succinctly
    posts: author => author.posts ? author.posts : author.getPosts()
    

    这样,我们只有在确实需要获取帖子时才调用getPosts。或者,您可以省略 posts 解析器并在您的 author 解析器中处理此问题。我们可以查看传递给解析器的第四个参数以获取有关请求的信息,包括请求了哪些字段。例如,您的解析器可能如下所示:

    author: (root, args, context, info) => {
      const include = []
      const requestedPosts = info.fieldNodes[0].selectionSet.selections.includes(s => s.name.value === 'posts'
      if (requestedPosts) include.push(Post)
      return Author.findAll({include})
    }
    

    现在,如果客户特别要求,您的解析器将只包含每位作者的帖子。提供给解析器的 AST 树对象很难解析,但有一些库(如 this one)可以帮助解决这个问题。

    【讨论】:

    • 谢谢,很好的回答。 Author 类型确实是错误的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-24
    • 2021-12-30
    • 2022-11-17
    • 1970-01-01
    • 1970-01-01
    • 2016-10-18
    相关资源
    最近更新 更多