我正在学习GraphQL,在我看到的每个示例中,signup
/ login
和me
调用都在mutation
和query
中类型。这是为什么?示例:
type Query {
me: User
}
type Mutation {
login(email: String!, password: String!): String
}
这不是User
类型吗?既然是与用户相关的事情?
如果这是一个基于观点的问题,我深表歉意,如果是这样,我将结束该问题。
答案 0 :(得分:0)
此问题基于GraphQL架构设计。设计是100%基于意见的事物。但是,让我尝试回答您的问题。
在login
突变答案中,客户端应收到auth令牌或类似令牌。每个token
都将作为Http标头发送,以进行身份验证请求。显然,此token
不是User
实体的一部分。在复杂的应用程序中,您可以设计如下的变异答案:
{
user: ...
token: ...
}
但是对于演示应用程序,只需令牌(字符串)作为login
突变答案即可。
答案 1 :(得分:0)
来自spec:
GraphQL可以进行三种类型的操作:
查询–只读访存。
变异–先写入,然后提取。
订阅–响应源事件而获取数据的长期请求。
每个操作都与特定类型相关联,尽管突变和订阅类型都是可选的。因此,可以这样定义一个模式:
schema {
query: Query
}
在这里,Query
是指名为Query
的类型。按照惯例,这三种类型分别命名为Query
,Mutation
和Subscription
,但是可以使用其他任何名称,这并不重要。但是,它们必须是对象类型,并且必须至少包含一个字段。
这些操作类型充当GraphQL操作的“根”,并且实际上是数据图的入口点。即使根目录中存在其他类型,也不会在根级别公开。
me
类型经常显示一个viewer
或Query
字段,以便允许用户提取当前登录的用户。假设我们已经定义了User
类型,如果我们在me
类型中添加Query
字段,并将该字段的类型设置为User
,则启用使用者端点编写类似以下的查询
query {
me {
# some set of User fields like id, firstName, etc.
}
}
如果我们将me
字段放在User
类型上,a)我们不一定有一种请求该字段的方法,因为它不在根部,并且b)我们会在我们返回me
的每个地方暴露一个User
字段(例如,一个返回friends
列表的Users
字段)没有任何意义。>
相同的逻辑适用于login
之类的突变-我们希望将它们置于操作的根源,因此将其放置在Mutation
类型内。另一方面,login
应该是突变还是查询,is subjective and depends on your particular use case。
如果您习惯使用REST,通常会看到带有操作的数据源前缀的操作,例如:
POST /articles/{id}/bookmark
我们可能倾向于对我们的突变实施类似的结构,从而导致如下请求:
mutation {
article {
bookmark
}
}
但是,这完全没有必要,实际上违反了约定并使实现更加复杂。只需要做:
mutation {
bookmarkArticle
}
有关这一点的更多信息,请参见here。
答案 2 :(得分:0)
这是两个独立的问题。
这里的第一个答案是,如果要进行GraphQL查询,则需要某种方式来获取对象以开始查询。没有像Java或其他面向对象的语言中可能看到的“静态方法”的概念;这些初始查询集必须在根Query
类型上。你可以想象
type Query {
"The currently logged-in user."
me: User!
"Find a user by their email address."
user(email: String!): User
}
拥有User
对象后,您可以查询其他字段,但是您需要某种方式来首先获取它。
query WhatsMyEmail {
me { email }
}
第二,所有更改数据的操作都是Mutation
类型的顶级字段。这主要是惯例,实际上并没有阻止您执行解析程序功能中的任何事情的方法,但这会带来很多关键影响。只需查询对象上的每个字段并从架构中生成类似的查询就很容易了:
fragment AllUserFields on User {
id, name, email, delete
}
query WhoAmI {
me { ...AllUserFields } # oops I deleted myself
}
您还可以保证顶级变异按顺序执行,但是GraphQL中的其他所有内容都可以按任何顺序执行。如果您的模式允许这样做,则email
可以是旧的或新的电子邮件地址,例如:
query ChangeMyEmail {
me {
changeEmail(email: "new@example.com")
email # is allowed to evaluate first and return old@example.com
}
}
诸如“登录”之类的东西实际上只是与任何特定对象无关的“动作”,仅附加到Mutation
而不是任何特定类型,才有意义。 (如果“登录”是User
的属性,是哪个属性,以及如何在未登录的情况下找到它?)