为啥每个 GraphQL 查询/突变都有“两个名称”?
Posted
技术标签:
【中文标题】为啥每个 GraphQL 查询/突变都有“两个名称”?【英文标题】:Why are there "two names" for each GraphQL query/mutation?为什么每个 GraphQL 查询/突变都有“两个名称”? 【发布时间】:2019-08-11 14:48:56 【问题描述】:我正在学习 GraphQL,有一个基本点让我感到困惑。我知道有一个简单的解释,但我找不到。具体来说,来自 Apollo 文档 (https://www.apollographql.com/docs/apollo-server/essentials/data.html#operation):
...为操作命名以便快速识别是有意义的 调试期间的操作或聚合类似操作 一起...操作可以通过在后面放置一个标识符来命名 查询或突变关键字,就像我们在此处使用 HomeBookListing 所做的那样:
query HomeBookListing
getBooks
title
如果HomeBookListing
是查询的名称,那么getBooks
是什么?解析器的名称?
同样,当你将变量传递给查询时,为什么会有“两级”参数,像这样
mutation HomeQuickAddBook($title: String, $author: String = "Anonymous")
addBook(title: $title, author: $author)
title
那么,$title: String, $author: String = "Anonymous"
是传递给查询的变量,title: $title, author: $author
是传递给解析器的变量吗?
我当然可以记住模式,但我很想从概念上理解不同的部分在这里做什么。任何见解都非常感谢!
【问题讨论】:
我已经有一段时间没有接触graphql了,但如果我没记错的话:“什么是getBooks” - 解析器的名称,是的。它不是“查询的第二个名称”。你可以在它旁边有getProducts
。它只是查询中的一个“字段”。
变异也一样:你为整个操作声明参数列表,那么操作的不同部分(addBook / addReview)将使用参数列表的不同子集。
@SergioTulentsev -- 谢谢。我认为这更多的是解析器本身中的单独“字段”,在服务器上,例如,您可以拥有const resolvers= Query: getBooks: async() => ...., getProducts: async() => ...
。我想这就是你所指的?
是的,确实如此。
【参考方案1】:
您可能会发现查看the spec 会有所帮助,但下面是一个简短的解释:
什么是操作?
GraphQL 中有三个操作(query
、mutation
和 subscription
)。通常,一个 GraphQL 请求只包含这三个操作中的一个,它构成了请求的根,或者是进入架构其余部分的入口点。
每个操作都有一个与之关联的对象类型。按照惯例,这些类型被命名为Query
、Mutation
和Subscription
,但它们的命名在功能上与您的模式无关。除了它们与特定操作的关联之外,这些对象类型并没有什么特别之处——每个对象类型都有一个name
、description
和fields
,就像架构中的任何其他对象类型一样。我们将这三种类型统称为根操作类型。
在您的示例中,query
根类型有一个名为getBooks
的字段。该字段根据与架构中的任何其他字段相同的规则进行解析。该字段唯一的特殊之处在于它位于根目录——在它之前没有解析过“父”字段。
操作名称是可选的,因为它们不会影响服务器返回的数据——它们通常用于调试目的(尽管一些客户端和工具使用它们来提供其他功能,所以拥有它们总是好的)。但是,为您的根操作类型指定至少一个字段名称是必要的,否则您的操作实际上不会做任何事情(即向服务器查询数据)。同样,这些字段是您进入架构其余部分的入口点和数据图的起点。
好的,但是变量呢?
根据规范:
变量必须在操作的顶部定义,并且在该操作的整个执行过程中都在范围内。
虽然我们没有用值初始化文档中的变量,但我们确实需要通过告诉 GraphQL 它是什么类型的变量来定义它。这允许 GraphQL 验证整个文档中变量的使用情况。例如,如果您将变量定义为 String
,然后尝试在 Int
的输入字段中使用它,则验证将失败,并且您的请求甚至在执行之前就会崩溃。
变量总是被定义为操作定义的一部分——它们可以在文档中的任何地方使用,甚至可以多次使用。所以这里没有“两级参数”——一行是简单的定义,另一行是用法。
关于语义的一句话
尽管我们有一个规范,但围绕 GraphQL 的语言已经超越了其中概述的术语。 “查询”一词具有多种含义,您在查看各种文档和文章时可能会遇到这些含义。记住这些定义有助于避免混淆:
按照惯例,我们将与query
操作关联的根操作类型命名为Query
类型
非正式地,Query
(即getBooks
)上的字段通常被称为架构的“查询”(就像Mutation
类型上的字段通常被称为你的架构。
我们发送到服务器的完整请求字符串,包括整个操作和任何相关的fragments,正式称为文档。但是,我们通常将发出请求称为查询您的服务器。这导致文档本身经常被称为查询,无论操作是包含实际上是 query
还是像 mutation
这样的不同操作。
【讨论】:
以上是关于为啥每个 GraphQL 查询/突变都有“两个名称”?的主要内容,如果未能解决你的问题,请参考以下文章
为啥我在尝试从 C# 处理程序发布 GraphQL 查询时收到错误请求?