美文网首页学习笔记
Graphql 架构和类型

Graphql 架构和类型

作者: 这里是廖同学 | 来源:发表于2019-08-06 15:15 被阅读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带有一组开箱即用的默认标量类型:

    • Int:带符号的32位整数。
    • Float:带符号的双精度浮点值。
    • String:UTF-8字符序列。
    • Booleantruefalse
    • ID:ID标量类型表示唯一标识符,通常用于重新获取对象或作为缓存的键。ID类型以与String相同的方式序列化; 但是,将其定义为ID表示它不是人类可读的。

    在大多数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!"
        }
      }
    }
    

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

    相关文章

      网友评论

        本文标题:Graphql 架构和类型

        本文链接:https://www.haomeiwen.com/subject/lntwdctx.html