学习笔记

Graphql 架构和类型

2019-08-06  本文已影响2人  这里是廖同学

在此文章上面,您将了解有关GraphQL类型系统以及如何描述可查询数据的所有信息。由于GraphQL可以与任何后端框架或编程语言一起使用,因此我们将远离特定于实现的细节,并仅讨论这些概念。

参数

GraphQL对象类型上的每个字段都可以包含零个或多个参数,例如length下面的字段:

type Starship {
  id: ID!
  name: String!
  length(unit: LengthUnit = METER): Float
}

主要看length字段 括号里面有一个unit参数 LengthUnit 表示如果没有给参数 参数为空的话 METER 就是默认值

Float 是类型

LengthUnit 表示设置默认参数

查询和变异类型

模式中的大多数类型只是普通的对象类型,但在模式中有两种特殊类型:

schema  { 
  query : Query 
  mutation : Mutation 
}

每个GraphQL服务都有一个query类型,可能有也可能没有mutation类型。这些类型与常规对象类型相同,但它们是特殊的,因为它们定义了每个GraphQL查询的入口点。因此,如果您看到如下查询:

这意味着GraphQL服务需要一个Query带有herodroid字段的类型:

type Query { 
  hero (episode : Episode ): Character 
  droid (id : ID !): Droid 
}

Mutation 跟以上Query 使用工作一样 ,区别就是 Query用于查询 Mutation 用于增删改 在什么场景使用那种类型即可

重要的是要记住,除了作为模式的“入口点”的特殊状态之外,QueryMutation类型与任何其他GraphQL对象类型相同,并且它们的字段以完全相同的方式工作。

基础类型

GraphQL对象类型具有名称和字段,但在某些时候,这些字段必须解析为某些具体数据。这就是基础类型的来源:他们用来表示字段的类型的

在以下查询中,nameappearsIn字段将解析为基础类型:

我们知道这一点,因为这些字段没有任何子字段 - 它们是查询的叶子. 默认是Query

GraphQL带有一组开箱即用的默认标量类型:

在大多数GraphQL服务实现中,还有一种指定自定义标量类型的方法。例如,我们可以定义一个Date类型:

scalar Date

nascimento: String @date

然后由我们的实现来定义应该如何序列化,反序列化和验证该类型。例如,您可以指定Date应始终将类型序列化为整数时间戳,并且您的客户端应该知道期望任何日期字段的格式。

枚举类型

枚举类型也称为枚举,是一种特殊的标量,仅限于一组特定的允许值。这允许您:

  1. 验证此类型的任何参数是否为允许值之一
  2. 通过类型系统进行通信,字段将始终是一组有限的值

以下是GraphQL模式语言中枚举定义的含义:

enum Episode {
  NEWHOPE
  EMPIRE
  JEDI
}

这意味着,无论我们使用的类型Episode在我们的模式,我们希望它是正好一个NEWHOPEEMPIREJEDI

请注意,各种语言的GraphQL服务实现将有自己的语言特定方式来处理枚举。在支持enum作为一等公民的语言中,实施可能会利用这一点; 在没有枚举支持的JavaScript语言中,这些值可能在内部映射到一组整数。但是,这些细节不会泄露给客户端,客户端可以完全根据枚举值的字符串名称进行操作。

列表和非空

对象类型,标量和枚举是您可以在GraphQL中定义的唯一类型。但是,当您在模式的其他部分或查询变量声明中使用类型时,可以应用影响这些值验证的其他类型修饰符。我们来看一个例子:

type Character {
  name: String!
  appearsIn: [Episode]!
}

在这里,我们使用一个String类型,并通过在类型名称后添加感叹号将其标记为Non-Null!。这意味着我们的服务器总是希望为该字段返回一个非空值,如果它最终得到一个实际触发GraphQL执行错误的空值,让客户端知道出现了问题。

在定义字段的参数时也可以使用Non-Null类型修饰符,如果将null值作为该参数传递,则会导致GraphQL服务器返回验证错误,无论是在GraphQL字符串中还是在变量中。

列表以类似的方式工作:我们可以使用类型修饰符将类型标记为a List,这表示此字段将返回该类型的数组。在模式语言,这是通过缠绕在方括号中的类型来表示,[]。它对于参数的作用相同,其中验证步骤将期望该值的数组。

可以组合Non-Null和List修饰符。例如,您可以拥有一个非空字符串列表:

myField : [ String !]

这意味着列表本身可以为null,但它不能包含任何null成员。例如,在JSON中:

myField : null  //有效 
myField : [ ]  //有效 
myField : [ 'a' , 'b' ]  //有效 
myField : [ 'a' , null , 'b' ]  //错误

现在,假设我们定义了一个非空字符串列表:

myField : [ String ] !

这意味着列表本身不能为null,但它可以包含空值:

myField : null  //错误 
myField : [ ]  //有效 
myField : [ 'a' , 'b' ]  //有效 
myField : [ 'a' , null , 'b' ]  //有效

您可以根据需要任意嵌套任意数量的Non-Null和List修饰符。

接口

与许多类型系统一样,GraphQL支持接口。一个接口是一个抽象类,其中包括一组特定的字段类型必须包括实现接口的。

例如,你可以有一个Character代表星球大战三部曲中任何角色的界面:

interface Character {
  id: ID!
  name: String!
  friends: [Character]
  appearsIn: [Episode]!
}

这意味着任何实现的 类型都Character需要具有这些参数和返回类型的精确字段。

例如,以下是可能实现的一些类型Character

type Human implements Character {
  id: ID!
  name: String!
  friends: [Character]
  appearsIn: [Episode]!
  starships: [Starship]
  totalCredits: Int
}

type Droid implements Character {
  id: ID!
  name: String!
  friends: [Character]
  appearsIn: [Episode]!
  primaryFunction: String
}

您可以看到这两种类型都具有Character接口中的所有字段,但也会引入额外的字段totalCreditsstarships以及primaryFunction特定于该特定类型字符的字段。

当您想要返回一个对象或一组对象时,接口很有用,但这些对象可能有几种不同的类型。

例如,请注意以下查询会产生错误:

hero字段返回类型Character,这意味着它可以是a HumanDroid取决于episode参数。在上面的查询中,您只能询问Character接口上存在的字段(不包括)primaryFunction

要询问特定对象类型的字段,您需要使用内联片段:

在查询指南的内联片段部分中了解有关此内容的更多信息。

大概就是 使用接口 可以用 ... on 接口名 { 字段 } 体现了什么类有什么字段吧

联盟类型

union SearchResult =  Human  |  机器人 |  星河

无论我们SearchResult在模式中返回一个类型,我们都可以获得a HumanDroidStarship。请注意,union类型的成员需要是具体的对象类型; 您无法使用接口或其他联合创建联合类型。

在这种情况下,如果查询返回SearchResult联合类型的字段,则需要使用条件片段才能查询任何字段:

__typename字段解析为String允许您在客户端上区分不同数据类型的字段。

此外,在这种情况下,由于HumanDroid共享一个公共接口(Character),您可以在一个地方查询它们的公共字段,而不必在多个类型中重复相同的字段:

{
  search(text: "an") {
    __typename
    ... on Character {
      name
    }
    ... on Human {
      height
    }
    ... on Droid {
      primaryFunction
    }
    ... on Starship {
      name
      length
    }
  }
}

请注意,name仍然指定,Starship因为否则它不会显示在给定的结果Starship不是Character

输入类型

到目前为止,我们只讨论过将标量值(如枚举或字符串)作为参数传递到字段中。但您也可以轻松传递复杂对象。这在突变的情况下特别有价值,您可能希望传递要创建的整个对象。在GraphQL架构语言中,输入类型看起来与常规对象类型完全相同,但使用关键字input而不是type

input ReviewInput {
  stars: Int!
  commentary: String
}

以下是如何在突变中使用输入对象类型:

mutation CreateReviewForEpisode($ep: Episode!, $review: ReviewInput!) {
  createReview(episode: $ep, review: $review) {
    stars
    commentary
  }
}
{
  "ep": "JEDI",
  "review": {
    "stars": 5,
    "commentary": "This is a great movie!"
  }
}
{
  "data": {
    "createReview": {
      "stars": 5,
      "commentary": "This is a great movie!"
    }
  }
}

输入对象类型上的字段本身可以引用输入对象类型,但不能在模式中混合输入和输出类型。输入对象类型也不能在其字段上包含参数。

上一篇下一篇

猜你喜欢

热点阅读