哪个是正确的旋转变压器功能方法?

时间:2017-11-24 00:21:42

标签: graphql apollo graphql-js react-apollo

我想澄清一下我应该在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()?

1 个答案:

答案 0 :(得分:1)

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

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

只要您的author查询总是解析为包含posts属性的对象数组,那么您就会认为它没有&#39 ;在posts类型的Author字段中包含客户解析程序是有意义的。在这种情况下,您的查询解析程序已经填充了所有必填字段,我们不必做任何其他操作。

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)可以帮助解决这个问题。