为什么我和我的注册始终都在突变和查询类型中?

时间:2019-02-18 21:10:16

标签: javascript graphql apollo-server

我正在学习GraphQL,在我看到的每个示例中,signup / loginme调用都在mutationquery中类型。这是为什么?示例:

type Query {
  me: User
}

type Mutation {
  login(email: String!, password: String!): String
}

这不是User类型吗?既然是与用户相关的事情?

如果这是一个基于观点的问题,我深表歉意,如果是这样,我将结束该问题。

3 个答案:

答案 0 :(得分:0)

此问题基于GraphQL架构设计。设计是100%基于意见的事物。但是,让我尝试回答您的问题。

login突变答案中,客户端应收到auth令牌或类似令牌。每个token都将作为Http标头发送,以进行身份​​验证请求。显然,此token不是User实体的一部分。在复杂的应用程序中,您可以设计如下的变异答案:

{
  user: ...
  token: ...
}

但是对于演示应用程序,只需令牌(字符串)作为login突变答案即可。

答案 1 :(得分:0)

来自spec

  

GraphQL可以进行三种类型的操作:

     
      
  • 查询–只读访存。

  •   
  • 变异–先写入,然后提取。

  •   
  • 订阅–响应源事件而获取数据的长期请求。

  •   

每个操作都与特定类型相关联,尽管突变和订阅类型都是可选的。因此,可以这样定义一个模式:

schema {
  query: Query
}

在这里,Query是指名为Query的类型。按照惯例,这三种类型分别命名为QueryMutationSubscription,但是可以使用其他任何名称,这并不重要。但是,它们必须是对象类型,并且必须至少包含一个字段。

这些操作类型充当GraphQL操作的“根”,并且实际上是数据图的入口点。即使根目录中存在其他类型,也不会在根级别公开。

me类型经常显示一个viewerQuery字段,以便允许用户提取当前登录的用户。假设我们已经定义了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的属性,是哪个属性,以及如何在未登录的情况下找到它?)