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