GraphQL简介
GraphQL 是一种用于 API 的查询语言。它使得客户端能够准确地获得它需要的数据,而且没有任何冗余
特点
不多不少的请求你需要的数据
发出一个 GraphQL 请求就能准确获得你想要的数据,不多不少。 GraphQL 查询总是返回可预测的结果。使用 GraphQL 的应用可以工作得又快又稳,因为控制数据的是应用,而不是服务器。
获取多个资源只需要用一个请求
GraphQL 查询不仅能够获得资源的属性,还能沿着资源间引用进一步查询。典型的 REST API 请求多个资源时得载入多个 URL,而 GraphQL 可以通过一次请求就获取你应用所需的所有数据。这样一来,即使是比较慢的移动网络连接下,使用 GraphQL 的应用也能表现得足够迅速。
完善的类型系统
GraphQL API 是基于类型和字段的方式进行组织的。GraphQL 使用强类型来保证请求数据的正确性,提前声明好类型可以避免编写代码手动进行解析。它还提供了清晰的辅助性错误信息。
API 演进无需划分版本
给你的 GraphQL API 添加字段和类型而无需影响现有查询。老旧的字段可以废弃,从工具中隐藏。通过使用单一演进版本,GraphQL API 使得应用始终能够使用新的特性,并鼓励使用更加简洁、更好维护的服务端代码。
使用你现有的数据和代码
GraphQL 让你的整个应用共享一套 API,而不用被限制于特定存储引擎。GraphQL 引擎已经有多种语言实现,通过 GraphQL API 能够更好利用你的现有数据和代码。你只需要为类型系统的字段编写函数,GraphQL 就能通过优化并发的方式来调用它们
一个GraphQL查询可以包含一个或者多个操作(operation),类似于一个RESTful API。操作有两种类型:查询(Query)或者修改(mutation)
查询
第一个demo
1 | query { |
user是查询的operation
(id: 1)包含了传入给Query的参数
查询包含id和name字段,这些字段也就是我们希望查询可以返回的数据
这时server返回的数据就类似下面这种:
1 | { |
第二个demo
1 | query { |
这次我们查询student,并传入两个参数:class_id班号用于过滤,order指明按照number学号进行降序排列。查询中包含的字段是:name、class_id、number和hometown)
应该能猜到返回的结果是什么样的了,没错,大概如下:
1 | { |
从上面两个例子里可以看出来GraphQL允许客户端明确指定它要的是什么,避免了数据后去的冗余或者不足。而RESTful API ,每一个客户端都会对应很多个RESTful API或者一个API要服务很多个客户端。
所以说GraphQL是很好的查询语言。所有的operation、参数和所有可以查询的字段都需要在GraphQL server上定义、实现。
嵌套查询
查询的嵌套没有限制,全看我们的查询和server的实现。比如可以使用下面的查询:
1 | { |
这里我们请求server返回某个客户的purchases。查询里不仅指定了purchase的字段,还指定了相关的product,product_category的名称。
强类型
官方文档有一句话如下:
“每一个GraphQL server都要定义类型系统。查询是在这个类型系统的上下文中执行的。”
也就是说,你可以查询值类型:Int, Float, String, Boolean和ID
如果想要查询object类型,就需要我们自己定义了。
由于GraphQL查询都是结构化的,信息也是类树结构展示的。我们可以这么简单的理解:值类型(Scalar Type)–叶子,对象类型(Object Type)–树干。
字段别名
在GraphQL查询中可以为Operation里的字段指定别名。
比如查询里指定了字段hometown,但是客户端只能接受jiaxiang。
因为查询的返回结果都包含在以operation名称为key的对象里,所以可以为这个名称设置一个别名:
1 | { |
返回的数据类似这样:1
2
3
4
5
6
7
8
9{
"data": {
" MrLi_student ": {
" class_id ": "1",
"name": "Bingle ",
" jiaxiang ": "jiujiang"
}
}
}
其他查询的功能
Fragments
一次查询的两个对象中包含了大量相同片段的时候,可以把重复的字段都提出来,放到一个fragment里;
用操作符“…” 就可以使用fragment了
变量
查询参数多处使用的时候,我们可以定义一个变量来方便使用
修改Mutation
GraphQL不仅可以用来查询数据,也可以创建、更新和销毁数据。
当然和查询一样,这些也需要server端有对应的实现。
增、删、改一类的operation在GraphQL里统称为Muration(修改)。
下面通过几个例子来演示一下mutation。
1 | mutation { |
我们现在指定operation的类型为mutation,而不是query。
在create_student操作里我们传入了创建一个student需要的数据,并最终返回一个查询集合:
1 | { |
修改和删除类似了,对应的update_student和destroy_student即可
定义文档
上个例子的createstudent、update student和destroy_ student这些operation都是在GraphQL server实现好的。那我们前台客户端怎么知道GraphQL server都实现了什么方法呢?于是就有了 定义文档
GraphQL会根据已经定义好的类型系统来自动生成出一个说明文档。这样你就不用一次一次的翻看代码,而直接查看文档来了解operation的全部实现细节。
如果你用的是express-graphql, 并设置graphiql为true的话,那么就会生成一个web的调试界面。在最右侧可以直接使用doc
查询所有的queryType类型的operation
1 | { |
对于mutation类型的操作也是类似的:
1 | { |
返回结果如下:
1 | { |
我们还可以具体查询operation的参数,比如:
1 | { |
结果如下:
1 | { |
你会看到server实现了一个create_student的修改operation,参数为name和class_id。
搭建一个简单的基于node的GraphQL Server
第一步初始化项目
创建工程目录 graphqlDemo
初始化项目,以及引入所需的包
1 | npm init -f |
第二步 mock数据
在项目根目录下创建 data 目录,并在该目录下创建 data.json 文件,并输入以下内容:
1 | { |
第三步 创建server.js文件
1 | import express from 'express' |
命令行运行:nodemon –exec babel-node –presets=es2015 server.js,
浏览器输入:http://localhost:3000 。显示 Hello!,说明你的 express 服务已经 OK 了。
第四步 编写GraphQL Schema
创建文件夹 /src/schema,并创建文件 index.js。
并在 index.js 文件中编写GraphQL Schema。Schema 是 GraphQL 请求的入口,用户请求的
GraphQL 将会对应到具体的 Schema。
1 | import { |
第五步 连接 schema
修改 server.js 文件,连接 schema。将 server.js 文件修改为以下内容:
1 | import express from 'express' |
这时,在浏览器中可以查看到如下界面:
在左边的空白处输入:
1 | { |
点击“运行”按钮,右边会出现结果:
1 | { |
总结
至此我们对GraphQL有了初步的认识,并且搭建了一个简单的node端的 GraphQL server
更深入的了解,可以查阅官方文档,连接如下:
如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理