我现在来总结一下GraphQL
首先
由于阅读了有关GraphQL的O’Reilly书籍,以及在业余时间涉猎了AppSync,所以现在为了公司内部的学习会议,我总结了一下关于GraphQL的内容。
GraphQL是一种查询语言。
GraphQL是一种用于Web API的查询和模式语言,可以简洁地描述客户端应用程序的数据模型和要求。它由Facebook的开发团队创建,目的是为了描述功能和要求。
查询语言和模式语言
以下是关于在这里处理的查询语言和模式语言的想法和描述。
-
- クエリ言語
クライアントアプリがGraphQLサーバーにリクエストを送信するための構文
スキーマ言語
GraphQLサーバーのデータ型の集合を定義するための構文
GraphQL的定位
在应用程序开发中使用的GraphQL的形象。
GraphQL服务器所执行的实际操作
APIサーバーとの通信を行う
もしくは直接データベースの操作を行う
クエリ構文を解析する
解釈した構文に基づいて処理(リゾルバ)が実行される
作为WEB API的查询功能
将要发送给GraphQL服务器的查询使用POST方法作为HTTP请求发送。以下是使用cURL的示例。
curl --location --request POST 'http://snowtooth.moonhighway.com/' \
--header 'Content-Type: application/json' \
--data-raw '{"query":"query {\r\n allLifts {\r\n name\r\n }\r\n}","variables":{}}
如果要测试查询请求,可以使用类似GraphiQL、GraphQL Playground或者Postman中的GraphQL功能。
查询的类型
在客户端应用程序中使用的查询语法中,可以使用三种操作。
-
- 查询
-
- 变更
- 订阅
查询
用于获取数据的操作。在字段中指定实际要获取的数据。以下是一个通过Snootooth来获取所有缆车的名称和状态信息的示例。
query getAllLifts {
allLifts {
name
status
}
}
突变
负责数据写入操作。基本上语法与查询相同。以下是使用前一页的Snowtooth更新某个Lift状态的示例。
mutation openLift {
setLiftStatus(id:"astra-express" status: OPEN) {
name
status
}
}
订阅
可以从服务器实时接收数据。例如,为了每次接收到通过mutation更新的状态,不需要每次都发起查询,可以使用订阅功能,通过WebSocket实时接收数据。以下是该语法的一个示例。
可以用以下语法实现每次都查询不成功。
subscription listenStatusChange {
liftStatusChange {
name
status
}
}
这里省略了对话。
-
- フラグメント
冗長な構文を共通化させる仕組み
ユニオン型
2つの異なるオブジェクト型をまとめる仕組み
インタフェース
実装すべきフィールドのリストを指定する抽象型
构建模式
為了實施GraphQL伺服器,首先需要設計一個資料類型的集合,也就是一個架構。可以參考以往文章中的實例來進行設計。
enum Category {
HOGEHOGE
HUGAHUGA
}
type Item {
id: String!
data: String!
category: Category!
}
type Query {
allItem: [Item]
allItemOnCategory(category: Category): [Item]
}
input ItemInput {
data: String!
category: Category!
}
type Mutation {
addItem(item: ItemInput!): Item
}
模样
类型是模式的核心。每种类型都对应一个字段。查询和变更也分别是类型中定义的可用作字段的查询和变更。
type Item {
id: String!
data: String!
category: Category!
}
type Query {
allItem: [Item]
allItemOnCategory(category: Category): [Item]
}
type Mutation {
addItem(item: ItemInput!): Item
}
标量类型和列表
每个字段都具有特定类型的数据,这些内置类型称为标量类型。例如,id字段的标量类型被定义为String。顺便提一下,通过添加String!和!可以表示该字段不会为空。
此外,通过使用[]将类型括起来,可以指定字段为类型的列表。例如,[Item]表示一个类型为Item的列表。
枚举
当我们想要在字段中定义只有有限选项的字符串输入和输出时,可以使用枚举( Enum )。
enum Category {
HOGEHOGE
HUGAHUGA
}
在这里创建的Category可作为字段类型使用。
输入式
用于参数的类型。用于将多个参数组合在一起。
input ItemInput {
data: String!
category: Category!
}
在这里创建的ItemInput只能用作参数。
在这里省略的故事
-
- カスタムスカラー型
独自で定義されたスカラー型。
ユニオン型
複数の型のうち一つを返す型。
インタフェース
型の中で必ず存在するフィールドを定義する抽象型。
解决者
解析器是返回特定字段的函数。它会针对在查询中指定的字段进行查询。以下是我在以往的文章中写的有关AppSync和CDK实现的示例。
...
itemDS.createResolver({
typeName: 'Query',
fieldName: 'allItem',
requestMappingTemplate: MappingTemplate.dynamoDbScanTable(),
responseMappingTemplate: MappingTemplate.dynamoDbResultList(),
})
itemDS.createResolver({
typeName: 'Mutation',
fieldName: 'addItem',
requestMappingTemplate: MappingTemplate.dynamoDbPutItem(
PrimaryKey.partition('id').auto(),
Values.projecting('item')),
responseMappingTemplate: MappingTemplate.dynamoDbResultItem(),
})
...
从直觉的角度来看,解析器是用于将请求和响应主体进行映射和内部处理的实现机制。
最后
-
- GraphQLを用いた開発では、スキーマとクエリの2つの言語を書くことになる
スキーマはAPIの仕様となるもの
クエリはクライアントアプリからのリクエスト
基本的にライブラリを用いた開発となる
手で実装するのはおそらく難解
GraphQL用のライブラリについては公式ページで紹介されている。
介绍了与GraphQL相关的问题和文章的链接。
N+1问题
N+1问题指的是在一个SQL中获取N个记录后,为了分别获取与每个记录相关联的记录而发出N个SQL的问题。当在GraphQL的解析器中使用SQL时,这个问题很容易引发。这篇文章对这个问题很有参考价值。
有没有技术可以替代REST API?
正如这篇文章所提到的那样,GraphQL也有其缺点。
-
- フルスクラッチでの実装が難しい(基本はライブラリ依存)
- 画像や動画などの大容量バイナリの扱いが難しい(JSONなので)
Redux对决GraphQL
这个话题在某个幻灯片的第28页表格上有明确而简明易懂的总结。
像这样的文章通常会对Apollo Client和Redux进行对比并展开讨论,正如某些文章所述。