GraphQL(二)- Schema 和 Resolver
在GraphQL中,Schema和Resolver是两个非常重要的概念,是编写GraphQL Server的2个基本单元
本文介绍GraphQL中的Schema和Resolver。
Schema
Schema定义了GraphQL中基于graph的数据格式
参考: https://graphql.org/learn/schema/
Type语言
GraphQL 服务可以用任何语言编写。由于我们不能依赖特定的编程语言语法(如 JavaScript)来讨论 GraphQL 模式,因此我们将定义自己的简单语言。我们将使用“GraphQL 模式语言”:它类似于查询语言,并允许我们以与语言无关的方式讨论 GraphQL 模式。
如用type定义一个对象:
type Book {
title: String!
author: String!
price: Float
year: Int
}
类型后加!代表这个属性是对象必不可少(Non-Nullable)的,否则是optional的
在object定义中,Query,Mutation和Subscription是不可用做类名的,而typedef这3者则定义了该schema中的Query,Mutaion和Subscription。
Scalar类型
GraphQL提供了5种基本数据类型,分别为:
String
UTF‐8 字符序列。Int
有符号的 32 位整数。Float
有符号的双精度浮点值。Boolean
true/falseID
ID 标量类型表示唯一标识符,通常用于重新获取对象或作为缓存的键。ID 类型的序列化方式与字符串相同,但是,将其定义为ID表示它不是可读的。
Enum
type中枚举类型的定义:
enum Days_of_Week{
SUNDAY
MONDAY
TUESDAY
WEDNESDAY
THURSDAY
FRIDAY
SATURDAY
}
注意数据传递后,枚举类型的内容会变成与枚举变量名字相同的String而不是Int
Array
Schema支持数组,经过数组可以批量Query数据,resolver也可以处理数组中的数据过滤等操作
type Character {
name: String!
appearsIn: [Episode]!
}
下面显示!分别定义在数组和数据类型之后的差别:
myField: [String!]
myField: null // valid
myField: [] // valid
myField: ['a', 'b'] // valid
myField: ['a', null, 'b'] // error`
myField: [String]!
myField: null // error
myField: [] // valid
myField: ['a', 'b'] // valid
myField: ['a', null, 'b'] // valid
Interface
和其它语言的面向对象概念一样,graphql也引入了继承的概念,
Interface
作为一种抽象类型存在,想要使用必须由实体的type继承。
interface Character {
id: ID!
name: String!
friends: [Character]
appearsIn: [Episode]!
}
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
}
Union
Schema中也支持Union类型作为多种类型的Union使用
union SearchResult = Human | Droid | Starship
Input
到目前为止,我们只讨论了将Scalar(如枚举或字符串)作为参数传递到字段中。但您也可以轻松传递复杂对象。这在突变的情况下特别有价值,因为您可能希望传入要创建的整个对象。在 GraphQL 模式语言中,输入类型看起来与常规对象类型完全相同,但使用关键字input
input ReviewInput {
stars: Int!
commentary: String
}
mutation CreateReviewForEpisode($review: ReviewInput!) {
createReview(review: $review) {
stars
commentary
}
}
Resolver
Resolver是为 GraphQL 查询生成响应的函数集合。简单来说,Resolver充当 GraphQL 查询处理程序。
参数
GraphQL 模式中的每个Resolver函数都接受四个位置参数,如下所示 -
fieldName:(root, args, context, info) => { result }
Resolver函数的示例如下所示 -
//resolver function with no parameters and returning string
greeting:() => {
return "hello from TutorialsPoint !!!"
}
//resolver function with no parameters and returning list
students:() => db.students.list()
//resolver function with arguments and returning object
studentById:(root,args,context,info) => {
return db.students.get(args.id);
}
下面给出的是参数及其描述 -
root
包含从父字段上的解析程序返回的结果的对象。args
一个对象,其中包含传递到查询中的字段的参数。context
这是特定查询中所有解析程序共享的对象。info
它包含有关查询的执行状态的信息,包括字段名称、从根到字段的路径。
Data Source
数据源是 Apollo Server 可用于封装从特定源(如数据库或 REST API)获取数据的类。这些类有助于在解决操作时处理缓存、重复数据删除和错误。
您的服务器可以使用任意数量的不同数据源。不必使用数据源来提取数据,但强烈建议使用它们。
Error Handling
当Query或者Mutation操作出现问题时,一般GraphQL会返回一个Error的Json信息,如:
{
"errors":[
{
"message":"Cannot query field \"__typenam\" on type \"Query\".",
"locations":[
{
"line":1,
"column":2
}
],
"extensions":{
"code":"GRAPHQL_VALIDATION_FAILED",
"exception":{
"stacktrace":[
"GraphQLError: Cannot query field \"__typenam\" on type \"Query\".",
" at Object.Field (/my_project/node_modules/graphql/validation/rules/FieldsOnCorrectTypeRule.js:48:31)",
" ...additional lines...",
]
}
}
}
]
}
错误信息可以是GraphQL自带Error类型或是我们在Resolver中throw,默认的错误类型有:
参考:https://www.apollographql.com/docs/apollo-server/v3/data/errors