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

Posted

技术标签:

【中文标题】GraphQL:在一次网络调用中查询和变异【英文标题】:GraphQL: Query and mutate in one network call 【发布时间】:2019-10-21 04:51:46 【问题描述】:

我将给出一个使用 GitHub GraphQL API 的具体示例(这是我要解决的特定问题),但总体而言,这个问题似乎可以推广到 GraphQL。

假设我想为存储库 pytorch/pytorch 上的问题 #1234 添加标签“高优先级”。根据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?在我的代码中,我知道我想要标签“高优先级”,但要实际将其传达给这个突变,我必须首先将“高优先级”解析为一个 ID,但先进行另一个 GraphQL 调用。我要标记的内容也是如此:我有一个 pytorch/pytorch#1234 形式的唯一标识符,但我没有 ID,我必须查找它。)

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

【问题讨论】:

【参考方案1】:

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

查询 - 只读获取。 mutation – 一个写入,然后一个提取。 订阅 – 一个长期存在的请求,用于获取数据以响应源事件。

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

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

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 而不是名称,为问题/PR 传递 ID 而不是数字这一事实是 Github 的设计选择。虽然在突变参数中看到由某种 id 字段显式引用的实体相当普遍,但规范中没有任何内容禁止突变接受其他标识符作为输入。

【讨论】:

以上是关于GraphQL:在一次网络调用中查询和变异的主要内容,如果未能解决你的问题,请参考以下文章

从 lambda 调用 AWS AppSync GraphQL API 变异查询

身份验证Apollo Graphql for android

GraphQL:如何重用相同的类型进行查询和变异?

在 GraphQL/Apollo 中使用带有变异查询的 Promise?

为啥注册和我总是在变异和查询类型中?

如何为 xunit 集成测试编写 GraphQL 变异查询