在 LeanCloud 中使用 GraphQL
因為 GraphQL 的支持需要伺服器端的更改,因此我選擇了在 LeanCloud 的數據服務的基礎上用 Node.js 編寫一個中間層,運行在雲引擎上,將 GraphQL 的查詢翻譯成對 LeanCloud SDK 的調用,為客戶端提供 GraphQL 支持。
我也參考了其他語言和框架的 GraphQL 支持,它們都需要開發者進行很多的開發或配置工作。這是因為無論在 MySQL 還是 MongoDB 中都並沒有記錄數據之間的關聯關係(Id 和 ObjectId 都不會記錄指向的表或集合,MySQL 的外鍵倒是會記錄,但可惜用戶不多);而且即使你定義了數據之間的關聯,你還是需要去定義許可權 —— 哪些用戶可以訪問哪些數據。
而 LeanCloud 的 Relation 和 Pointer 都記錄了所指向的 Class,同時 LeanCloud 本身也有一套基於 sessionToken 和 ACL 的許可權控制機制,因此我們完全可以做到從 LeanCloud 的數據服務獲取數據之間的管理,然後遵循現有的 ACL 來自動實現對 GraphQL 的支持。
leancloud/leancloud-graphql 就是這樣的一個項目,你只需將它部署到雲引擎上,不需要改動一行代碼,便可以用 GraphQL 查詢你在 LeanCloud 上的所有數據。
相較於 RESTful 和 SQL,GraphQL 為數據定義了嚴格的類型,你可以使用這樣一個靈活的語言將數據通過關係組合起來,所見即所得地得到你想要的數據。得益於 GraphQL 的類型系統,你還可以在調試工具(graphql.leanapp.cn)中得到精確的錯誤提示和補全建議。
例如這裡我們查詢 Todo 這個 Class 中按優先順序排序的前兩條數據,獲取 title、priority,並將 owner 這個 Pointer 展開:
query {n Todo(ascending: priority, limit: 2) {n title, priority, owner {n usernamen }n }n}n
結果:
{n Todo: [{n title: "緊急 Bug 修復",n priority: 0,n owner: {n username: "someone"n }n }, {n title: "打電話給 Peter",n priority: 5,n owner: {n username: "someone"n }n }]n}n
目前 leancloud-graphql 已經實現了 LeanCloud 中大部分的查詢參數和查詢條件,你可以任意地組合這些條件。例如我們可以查詢優先順序大於 5 且存在 content 屬性的數據:
query {n Todo(exists: {content: true}, greaterThan: {priority: 5}) {n title, content, priorityn }n}n
GraphQL 最大的亮點還是對關係查詢的支持,無論是 Relation 還是 Pointer 你都可以任意地展開,而不必受到 LeanCloud RESTful API 只能展開一層的限制。例如我們查詢所有的 TodoFolder 中的 Todo(Relation)並展開 owner(Pointer):
query {n TodoFolder {n name,n containedTodos {n title, owner {n username, emailn }n }n }n}n
結果(省略了一部分):
{n TodoFolder: [{n name: "工作",n containedTodos: [{n title: "緊急 Bug 修復",n owner: {n username: "someone",n email: "test@example.com"n }n }, // ...n ]n }, // ...n ]n}n
你也可以在關係查詢上附加查詢參數或條件。例如我們查詢所有 TodoFolder 中優先順序最高的一個 Todo:
query {n TodoFolder {n name, containedTodos(limit: 1, ascending: priority) {n title, priorityn }n }n}n
結果:
{n TodoFolder: [{n name: "工作",n containedTodos: [n {title: "緊急 Bug 修復", priority: 0}n ]n }, n name: "購物清單",n containedTodos: [n {title: "買酸奶", priority: 10}n ]n }, {n name: "someone",n containedTodos: [n {title: "緊急 Bug 修復", priority: 0}n ]n }]n}n
在實現一對多關係時,我們經常會在「多」上面保存一個到「一」的指針,例如一個 Todo 會有一個叫 owner 的 Pointer 指向用戶表。在這時,leancloud-graphql 會自動在用戶表上添加一個叫 ownerOfTodo 的屬性用來表示這個反向關係,你可以像展開一個 Relation 一樣展開這個反向關係,例如我們查詢每個用戶的 Todo 並展開 title:
query {n _User {n username, ownerOfTodo {n titlen }n }n}n
結果:
{n _User: [{n username: "someone",n ownerOfTodo: [n {title: "緊急 Bug 修復"},n {title: "打電話給 Peter"},n {title: "還信用卡賬單"},n {title: "買酸奶"}n ]n }]n}n
對 leancloud/leancloud-graphql 的簡單介紹就到這裡,更多使用方法和功能介紹可以在項目的 GitHub 主頁上看到,這個項目本身也是開源的。
推薦閱讀:
※leancloud用戶系統
※LeanCloud 層層加固雲端數據安全性之剖析
※如何優雅地修改前同事的混亂代碼?
※從 HTTP 0.9 到 QUIC
※線程之間傳遞 ThreadLocal 對象