GraphQL:在一次网络调用中进行查询和变异

GraphQL: Query and mutate in one network call

我将给出一个使用 GitHub GraphQL API 的具体示例(这是我想要解决的特定问题),但这个问题似乎一般适用于 GraphQL。

假设我想为存储库 pytorch/pytorch 上的问题 #1234 添加标签 'high priority'。根据 API 文档,我应该使用突变 https://developer.github.com/v4/mutation/addlabelstolabelable/ 输入要求:

labelIds ([ID!]!)
The ids of the labels to add.

labelableId (ID!)
The id of the labelable object to add labels to.

好的,我如何获得 ID?在我的代码中,我知道我想要标签 'high priority',但要将其实际传达给此突变,我必须首先将 'high priority' 解析为 ID,但首先进行另一个 GraphQL 调用。我要标注的也是一样:我有一个唯一的标识符,形式为pytorch/pytorch#1234,但我没有ID,我得查一下。)

所以在一天结束的时候,我必须做 三个 API 调用来标记一些东西,而我本可以在 REST 中完成它而不是一个称呼。总的来说,我看到很多 GraphQL 突变 APIs 只在 ID 中说话(即使系统有一些其他规范标识符可用),我最终不得不进行额外的往返。我做错了吗?或者这真的是 GraphQL 的设计方式吗?

根据 spec,一个 GraphQL 文档可以包含任意数量的 操作 ,其中一个操作是 querymutationsubscription.

  • query – a read‐only fetch.
  • mutation – a write followed by a fetch.
  • subscription – a long‐lived request that fetches data in response to source events.

对于一个特定的请求只能执行一个操作(如果提供了多个操作,则必须提供一个operationName来指定要执行的操作)。

但是,在该操作中,可以请求任意数量的字段。因此,如果您需要两个或更多 root-level 查询字段(通俗地称为 "queries"),它们可能会集中在一个操作中:

query ArbitraryOperationName {
  getSomething
  getSomethingElse
}

突变同上——您可以执行两个或更多突变(按顺序):

mutation ArbitraryOperationName {
  doSomething
  doSomethingElse
  doAThirdAction
}

因此,您需要将请求拆分为多个请求的唯一情况是:

  • 您需要同时执行 querymutation -- 这些是单独的操作,因此必须单独发送。
  • 您需要提供一个查询的部分结果作为另一个查询的输入。

您应该能够在单个查询中同时获取标签 ID 和问题 ID:

query {
  repository(owner: "graphql", name: "graphql-js") {
    label(name: "help wanted") {
      id
    }
    issue(number: 100) {
      id
    }
  }
}

但是,您的变更必须是一个单独的请求,因为 1) 它是一个不同的操作,并且 2) 它需要上述查询返回的输入数据。

也就是说,addlabelstolabelable 要求您为标签传递 ID 而不是名称,为 issues/PRs 传递 ID 而不是数字是 [=49= 的设计选择].虽然在突变参数中看到实体被某种 id 字段显式引用是很常见的,但规范中没有任何内容禁止突变接受其他标识符作为输入。