GraphQL介紹&使用nestjs構建GraphQL查詢服務(文章底部附demo地址)
GraphQL一種用為你 API 而生的查詢語言。出自於Facebook,GraphQL非常易懂,直接看查詢語句就能知道查詢出來的數據是什么樣的。本質上屬於API Layer層,負責前端請求的合並、數據整理等功能。

查詢示例
使用幾個簡單的例子看下GraphQL的查詢是什么樣子的。
普通查詢
{
me {
name
}
}
查詢出來的數據格式如下:
{
"me": {
"name": "wanghao"
}
}
1、返回來的數據是一個json
2、返回數據格式和查詢完全一致
帶參數的嵌套查詢
入參格式:
{
user(id: 6) {
name,
profilePicture {
width,
height,
url
}
}
}
查詢出來的數據如下:
{
"me" {
"name": "wanghao,"
"profilePicture": {
"width": 50,
"height": 50,
"url": "https://cdn/some.jpg"
}
}
}
當然,profilePicture查詢時也可以指定參數:
{
me {
name,
profilePicture(size: 300) {
width,
height,
url
}
}
}
輸出可能如下:
{
"me" {
"name": "wanghao,"
"profilePicture": {
"width": 300,
"height": 300,
"url": "https://cdn/300.jpg"
}
}
}
指定別名查詢
有時候同一字段我們想要查詢兩次,但是兩次指定的參數不同,比如一個用戶有多張頭像,我們只想查詢其中的2張,可以如下:
{
me {
name,
littlePic: profilePicture(size: 50) {
width,
height,
url
},
bigPic: profilePicture(size: 300) {
width,
height,
url
}
}
}
輸出結果如下:
{
"me" {
"name": "wanghao,"
"littlePic": {
"width": 50,
"height": 50,
"url": "https://cdn/50.jpg"
},
"bigPic": {
"width": 300,
"height": 300,
"url": "https://cdn/300.jpg"
}
}
}
更多查詢請參考:http://graphql.cn/learn/queries/
變更
查詢只適用於數據查詢,但是往往接口還有部分新增、修改、刪除操作,這個時候就需要使用變更(Mutations)。
想要新增一條數據,簡單的變更入參如下:
mutation($inputComment: CommentInput!) {
addComment(data: $inputComment)
}
其中$inputComment是GraphQL中的變量寫法,具體如下:
{
"inputComment": {
"postId": "5a796104fe9b131a10d9627d",
"text": "測試評論部分23232"
}
}
返回數據直接如下:
{
"data": {
"addComment": true
}
}
實際請求時的數據格式
GraphQL請求時不限制get、post請求,如果是get,會自動將請求體放在query中,看下實際請求時入參是什么樣子的:
{
query: "mutation($inputComment: CommentInput!) {↵ addComment(data: $inputComment)↵}↵↵"
variables: "{↵ "inputComment": {↵"postId":"5a796104fe9b131a10d9627d",↵"text":"測試評論部分23232"↵}"
}
可以看出,請求時實際發送的是一串字符串至GraphQL服務器,GraphQL服務器會自動解析該字符串內容。
GraphQL可視化查詢工具
GraphQL的所有實現基本都有實現該可視化工具,進行簡單配置即可查看,express-graphql模塊配置如下:
// GraphqQL server route
app.use('/graphql', graphqlHTTP(req => ({
schema,
pretty: true, // 配置顯示pretty按鈕進行代碼美化
graphiql: true, // 配置開啟可視化查詢
})));



dataloader
N+1查詢問題
# 定義
type User {
name: String,
friends: [User]
}
#查詢
{
users {
name
friends {
name
friends {
name
}
}
}
}
GraphQL支持嵌套查詢,如果沒有dataloader,就會出現嚴重的N+1查詢性能問題。
Dataloader(官方網址)是由facebook推出,能大幅降低數據庫的訪問頻次,經常在Graphql場景中使用。

import Sequelize from 'sequelize'
import DataLoader from 'dataloader'
// 定義表結構
const sequelize = new Sequelize('test', null, null, {
dialect: 'sqlite',
})
const UserModel = sequelize.define('user', {
name: Sequelize.STRING
})
await sequelize.sync({force: true})
//插入測試數據
await [
UserModel.create({name: 'ron'}),
UserModel.create({name: 'john'}),
]
// 初始化DataLoader,傳入一個批處理函數
const userLoader = new DataLoader(keys => UserModel.findAll({where: {name: {$in: keys}}}))
// 以下2個Load語句會被自動批處理,合並成一次數據庫的操作
await [
userLoader.load('ron'),
userLoader.load('john')
]
Executing (default): SELECT id, name, createdAt, updatedAt FROM users AS user WHERE user.name IN ('ron', 'john’);
DataLoader緩存的典型應用是per-request范圍的緩存,不能取代redis等應用級別的緩存。
使用nestjs構建GraphQL Server服務
nestjs,官網地址:https://docs.nestjs.com,是一個使用typescript構建nodejs后端應用的框架,類似java中的spring框架:依賴注入、攔截器、過濾器、裝飾器模式等等,比較看好。
使用nestjs搭配GraphQL、typeorm、mysql實現了一個簡單的GraphQL查詢服務,查詢支持單個查詢、列表查詢、關聯查詢,變更支持修改、刪除操作,具體demo地址: https://github.com/caiya/graphql-nestjs-typeorm
