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 文档可以包含任意数量的 操作 ,其中一个操作是 query
、mutation
或 subscription
.
- 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
}
因此,您需要将请求拆分为多个请求的唯一情况是:
- 您需要同时执行
query
和 mutation
-- 这些是单独的操作,因此必须单独发送。
- 您需要提供一个查询的部分结果作为另一个查询的输入。
您应该能够在单个查询中同时获取标签 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 字段显式引用是很常见的,但规范中没有任何内容禁止突变接受其他标识符作为输入。
我将给出一个使用 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 文档可以包含任意数量的 操作 ,其中一个操作是 query
、mutation
或 subscription
.
- 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
}
因此,您需要将请求拆分为多个请求的唯一情况是:
- 您需要同时执行
query
和mutation
-- 这些是单独的操作,因此必须单独发送。 - 您需要提供一个查询的部分结果作为另一个查询的输入。
您应该能够在单个查询中同时获取标签 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 字段显式引用是很常见的,但规范中没有任何内容禁止突变接受其他标识符作为输入。