GraphQL介紹&使用nestjs構建GraphQL查詢服務

GraphQL介紹&使用nestjs構建GraphQL查詢服務(文章底部附demo地址)

GraphQL一種用爲你 API 而生的查詢語言。出自於Facebook,GraphQL很是易懂,直接看查詢語句就能知道查詢出來的數據是什麼樣的。本質上屬於API Layer層,負責前端請求的合併、數據整理等功能。前端

查詢示例

使用幾個簡單的例子看下GraphQL的查詢是什麼樣子的。java

普通查詢

{
  me {
    name
  }
}

查詢出來的數據格式以下:node

{
  "me": {
    "name": "wanghao"
  }
}

一、返回來的數據是一個json
二、返回數據格式和查詢徹底一致mysql

帶參數的嵌套查詢

入參格式:git

{
  user(id: 6) {
    name,
    profilePicture {
      width,
      height,
      url
    }
  }
}

查詢出來的數據以下:github

{
  "me" {
    "name": "wanghao,"
    "profilePicture": {
      "width": 50,
      "height": 50,
      "url": "https://cdn/some.jpg"
    }
  }
}

固然,profilePicture查詢時也能夠指定參數:redis

{
  me {
    name,
    profilePicture(size: 300) {
      width,
      height,
      url
    }
  }
}

輸出可能以下:spring

{
  "me" {
    "name": "wanghao,"
    "profilePicture": {
      "width": 300,
      "height": 300,
      "url": "https://cdn/300.jpg"
    }
  }
}

指定別名查詢

有時候同一字段咱們想要查詢兩次,可是兩次指定的參數不一樣,好比一個用戶有多張頭像,咱們只想查詢其中的2張,能夠以下:sql

{
  me {
    name,
    littlePic: profilePicture(size: 50) {
      width,
      height,
      url
    },
    bigPic: profilePicture(size: 300) {
      width,
      height,
      url
    }
  }
}

輸出結果以下:typescript

{
  "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

相關文章
相關標籤/搜索