β

GraphQL系列二 数据类型

宅前疯 312 阅读

GraphQL是应用层查询语言,它有自己的数据类型,用来描述数据,比如标量类型、集合类型、Object类型、枚举等,甚至有接口类型。而GraphQL服务端不依赖任何语言,因此本篇只是从概念上来了解其数据类型。
GraphQL

标量类型(Scala)

标量类型是不能包含子字段,主要有如下类型:

以上的类型是GraphQL规范的基本类型,每个规范的实现也可以有自定以标量,如 scala Date ,但它必须能够序列和反序列化,至于如何定于取决于具体的规范实现。

枚举(Enum)

枚举类型是标量类型的变体,不仅适用于可验证性,还提高了维护性,它同样被序列化为String。定义形如

type User{
  name: String
  sex: String
  intro: String
}

以上定义了一个User对象,包含name(名字)、sex(性别)、intro(介绍)属性字段,而这些属性字段都是标量String类型,当然属性也可以是对象类型。

集合(List)

GraphQL规范中的集合只有List一种,它是有序的用 [] 表示,如

type Query {
user(id:Int!):User
}
type User{
name: String!
sex: String
intro: String
skills: [String]!
}

以上定义了查询接口user,其中参数id为必须提供,如果你使用如下查询语句

{
"errors": [
{
"message": "Field \"user\" argument \"id\" of type \"Int!\" is required but not provided.",
"locations": [
{
"line": 2,
"column": 3
}
]
}
]
}

而实体类型User的name为非null,一但服务端返回的数据name为null,则反馈为

schema {
query: Query
mutation: Mutation
}

一个Schema可以没有mutaion,但必须有query。
可以使用操作名为”__schema”和”__type”来查看schema和类型信息,签名如下

type __Schema {
types: [__Type!]!
queryType: __Type!
mutationType: __Type
subscriptionType: __Type
directives: [__Directive!]!
}

type __Type {
kind: __TypeKind!
name: String
description: String

# OBJECT and INTERFACE only
fields(includeDeprecated: Boolean = false): [__Field!]

# OBJECT only
interfaces: [__Type!]

# INTERFACE and UNION only
possibleTypes: [__Type!]

# ENUM only
enumValues(includeDeprecated: Boolean = false): [__EnumValue!]

# INPUT_OBJECT only
inputFields: [__InputValue!]

# NON_NULL and LIST only
ofType: __Type
}

type __Field {
name: String!
description: String
args: [__InputValue!]!
type: __Type!
isDeprecated: Boolean!
deprecationReason: String
}

type __InputValue {
name: String!
description: String
type: __Type!
defaultValue: String
}

type __EnumValue {
name: String!
description: String
isDeprecated: Boolean!
deprecationReason: String
}

enum __TypeKind {
SCALAR
OBJECT
INTERFACE
UNION
ENUM
INPUT_OBJECT
LIST
NON_NULL
}

type __Directive {
name: String!
description: String
locations: [__DirectiveLocation!]!
args: [__InputValue!]!
}

enum __DirectiveLocation {
QUERY
MUTATION
SUBSCRIPTION
FIELD
FRAGMENT_DEFINITION
FRAGMENT_SPREAD
INLINE_FRAGMENT
}

查询(Query)

Query目的是获取数据。格式

query userQuery{
user(id:0){
name
sex
stature
}
users{
name
sex
stature
}
}

实际上如果只有一个查询,“query”“queryName”都可以省略,如

mutation mutationName{
operation
}


{
user(id:1) {
name
sex
intro
skills
stature(unit:MM)
}
}

服务返回数据

query(
$noWithDog:Boolean!,
$withName:Boolean!,
$withFish:Boolean!
){
animals{
name @include(if:$withName)
... dogQuery @skip(if:$noWithDog)
... on Fish @include(if:$withFish){
tailColor
}
}
}
fragment dogQuery on Dog{
legs
}

在query定义中分别定义了$noWithDog(是否带着狗狗)、$withName(是否带着Name)、$withFish(是否带着鱼儿)变量,传入的参数变量为

{
"data": {
"animals": [
{
"name": "dog"
},
{
"name": "fish",
"tailColor": "red"
}
]
}
}

至于如何传参数,将在下一篇博文中演示。

如果参数变量传给非空的字段,那么参数变量也必须是非空类型,否则可以允许为空,允许为空是属于可选参数。而且参数变量可以有默认值值,如

input UserInput {
name: String!
sex: String
intro: String
skills: [String]!
}

定义了一个输入类型UserInput,字段有name、sex、intro和skills.

接口(Interface)

类似其他语言,GraphQL也有接口的概念,方便查询时返回统一类型,接口是抽象的数据类型,因此只有接口的实现才有意义,如

type Query {
animals:[Animal]!
}

而客户端的查询需要使用下面的Fragment,稍后展示。

联合(Union)

联合查询,类似接口式的组合,但不要求有公共字段,使用union关键字来定义,如

{
animals{
name
... on Dog{
legs
}
... on Fish{
tailColor
}
}
animalSearch(text:"dog"){
name
... on Dog{
legs
}
... on Fish{
tailColor
}
}
}

如果是Dog则查询legs字段,如果是Fish则查询tailColor字段,这种内联如果单个查询则比较方便,但多个查询则使用外联更简洁,如下

{
animals{
... on Dog{
chinaName
legs
}
... on Fish{
englishName
tailColor
}
}
}

别名(Alias)

GraphQL支持别名命名,这对于查询多个雷同的结果非常有用,格式为 aliasName: orginName

{
"data": {
"james": {
"name": "James",
"sex": "男",
"intro": "zhaiqianfeng的英文名",
"skills": [
"Linux",
"Java",
"nodeJs",
"前端"
],
"MM": 1.8,
"mm": 180
},
"zhaiqianfeng": {
"name": "zhaiqianfeng",
"sex": "男",
"intro": "博主,专注于Linux,Java,nodeJs,Web前端:Html5,JavaScript,CSS3",
"skills": [
"Linux",
"Java",
"nodeJs",
"前端"
],
"MM": 1.8,
"mm": 180
}
}
}

解析(resolve)

GrapQL API有一个入口点,通常称为“Root”,而查询都是由Root开始,如服务端定义一个root

{
user {
name
sex
intro
}
}

其实常用的是使用resolver,resolver是一个函数,用来处理数据,GraphQL规范中resolver的原型是 function(obj,args,context) :

比如express-graphql的是 function(args,context) ,省略了第一个obj。因此上例中你可以使用resolver来处理,比如:

var root= {
user: function(args,context){
return {
name: 'zhaiqianfeng',
sex: '男',
intro: '博主,专注于Linux,Java,nodeJs,Web前端:Html5,JavaScript,CSS3'
}
}
};

GraphQL是应用层查询语言,它有自己的数据类型,用来描述数据,比如标量类型、集合类型、Object类型、枚举等,甚至有接口类型。而GraphQL服务端不依赖任何语言,因此本篇只是从概念上来了解其数据类型。
GraphQL

作者:宅前疯
专注于Linux,Java,nodeJs,Web前端
原文地址:GraphQL系列二 数据类型, 感谢原作者分享。

发表评论