什么是 GraphQL?


GraphQL 是一種針對 Graph(圖狀數據)進行查詢特別有優勢的 Query Language(查詢語言),所以叫做 GraphQL。它跟 SQL 的關系是共用 QL 后綴,就好像「漢語」和「英語」共用后綴一樣,但他們本質上是不同的語言。GraphQL 跟用作存儲的 NoSQL 沒有必然聯系,雖然 GraphQL 背后的實際存儲可以選擇 NoSQL 類型的數據庫,但也可以用 SQL 類型的數據庫,或者任意其它存儲方式(例如文本文件、存內存里等等)。

GraphQL 最大的優勢是查詢圖狀數據。GraphQL 是 Facebook 發明的,我可以用 Facebook 做例子。例如說,你要在 Facebook 上打開我的頁面查看我的信息,你需要請求如下信息:

  • 我的名字
  • 我的頭像
  • 我的好友(按他們跟你的親疏程度排序取前 6):
    • 好友 1 的名字、頭像及鏈接
    • 好友 2 的名字、頭像及鏈接
    • ……
  • 我的照片(按時間倒序排序取前 6):
    • 照片 1 及其鏈接
    • 照片 2 及其鏈接
    • ……
  • 我的帖子(按時間倒序排序):
    • 帖子 1:
      • 帖子 1 內容
      • 帖子 1 評論:
        • 帖子 1 評論 1:
          • 帖子 1 評論 1 內容
          • 帖子 1 評論 1 作者名字
          • 帖子 1 評論 1 作者頭像
        • 帖子 1 評論 2:
          • ……
        • ……
    • 帖子 2:
      • 帖子 2 內容
      • 帖子 2 評論:
        • ……
    • ……

這是一個超級復雜的樹狀結構,如果我們用常見的 RESTful API 涉及,每個 API 負責請求一種類型的對象,例如用戶是一個類型,帖子是另一個類型,那就需要非常多個請求才能把這個頁面所需的所有數據拿回來。而且這些請求直接還存在依賴關系,不能平行地發多個請求,例如說在獲得帖子數據之前,無法請求評論數據;在獲得評論數據之后,才能開始請求評論作者數據。

如何解決這種問題?一個簡單粗暴的辦法是專門寫一個 RESTful API,請求上述樹狀復雜數據。但很快新問題就會出現。現在 Facebook 想要做一個新的產品,例如說是寵物,然后要在我的頁面上顯示我的寵物信息,那這個 RESTful API 的實現就要跟着改。

GraphQL 能夠很好地解決這個問題,但前提是數據已經以圖的數據結構進行保存。例如上面說到的用戶、帖子、評論是頂點,而用戶跟用戶發過的帖子存在邊的關系,帖子跟帖子評論存在一對多的邊,評論跟評論作者存在一對一的邊。這時候如果新產品引入了新的對象類型(也就是頂點類型)和新的邊類型,那沒有關系。在查詢數據時用 GraphQL 描述一下要查詢的這些邊和頂點就行,不需要去改 API 實現。


說完了 GraphQL 是什么和能解決什么問題,說說不夠好的地方吧。

第一,Facebook 從來沒有公開自己的 GraphQL 后端設計,使得大家必需要用第三方的,但體驗顯然不如我們在 Facebook 內部使用 GraphQL 好。我上面說了,數據必需已經以圖的數據結構進行存儲才有優勢。Facebook 內部有非常好的后端做好了這件事情,而且還內置了基於隱私設置的訪問控制。例如說你發的帖子有些是所有人可見的、有些是好友可見的、有些是僅同事可見的,我在打開你的頁面時 Facebook 有一個中間層保證了根據我和你的關系我只能看到我該看到的帖子。GraphQL 在這一層之上,所以無論 GraphQL 怎么寫我都不可能看到我不該看到的信息。

第二,並不是所有場景都適用於 GraphQL 的,有些很簡單的事情就應該用 RESTful API 來實現。Facebook 內部用戶增長部門的很多 API 都還不是 GraphQL,因為沒必要遷移到 GraphQL。用戶增長部門的 API 處理新用戶注冊、填寫短信驗證碼之類的事情,這些事情都是圍繞着一個用戶的具體某項或多項信息發生的,根本沒有任何圖的概念。可以強行寫作 GraphQL,但得不到顯著的好處。既然老的 API 早就寫好了,需要的時候做一些小改動,但沒必要重寫。

第三,GraphQL 盡管查詢的數據是圖狀數據結構,但實際獲得的數據視圖是樹狀數據結構。每一個 GraphQL 查詢或更新都有自己的根節點,然后所有的數據都是從根結點展開出去的。查詢后獲得的數據如果要在前端重新變回圖的狀態,那前端就不能簡單地緩存查詢得到的數據,必須用對用的 GraphQL 存儲庫,然后通過頂點的 ID 把不同節點之間的某些邊重新連接起來。

 
繼續瀏覽內容
知乎
發現更大的世界
打開
Chrome
繼續
 
 

沒有關系,QL = Query Language, 是查詢語言的簡稱,但它其實是一種規范~ 更多的是類比於 RESTful API。正好最近總結了一篇文章,暫時粘貼過來~

GraphQL 淺談,從理解 Graph 開始

前言

GraphQL is a data query language developed internally by Facebook in 2012 before being publicly released in 2015. It provides an alternative to RESTful architectures. —— from wikipedia.

GraphQL 是 Facebook 於 2012 年在內部開發的數據查詢語言,在 2015 年開源,旨在提供 RESTful 架構體系的替代方案。

掘金翻譯計划在今年 10 月上線了 GraphQL 中文官網,最近它的討論和分享逐漸增多。其實阿里內不少業務線早有嘗試和分享,聽聞基於 GraphQL 再造了個 TQL。也在其開源的Node.js企業級框架egg中,發布了對應的 plugin。感覺這是一個讓廣大(前端)開發者(重新)認識學習GraphQL的好機會,就讓我們來回顧一下它~

從 Graph 字面開始

先看官網的解釋~

GraphQL 既是一種用於 API 的查詢語言也是一個滿足你數據查詢的運行時。

總結的稍顯高深,簡單拆解一下:

SQL (Structured Query Language) 是結構化查詢語言的簡稱。所以Graph+ QL =圖表化(可視化)查詢語言,是一種描述客戶端如何向服務端請求數據的API語法,類似於 RESTful API 規范。

注:不要聯想到 MySQL、NoSQL,它不是圖形數據庫,比如 Neo4j
GraphQL 有配套的數據庫服務, graphcool 可以部署在 Docker 上或運行在基於 BaaS(Backend as a Service) 的 Graphcool Cloud。但它不依賴任何數據庫,且能和任何后端(SQL、MongoDB、Redis 等)一起使用,也可以包裹在 RESTful API 之上。

GraphQL 的特性

它定義了一套類型系統(Type System),類似於持續演進(相互借鑒)的FlowTypeScript,用來描述你的數據,先看官網的例子(細節再議)

項目的type type Project { name: String tagline: String contributors: [User] // 數組表示多個,type 為下面的 User } type User { name: String photo: String, friends: [User] // User 的朋友們, type 還是 User } 

接下來你可以把GraphQL查詢語言(Queries)當成是沒有值只有屬性的對象,返回的結果就是有對應值的對象,也就是標准的JSON

請求你所要的數據 // 基於 Queries { // 查找 name GraphQL project project(name: "GraphQL") { tagline } } 得到可預測的結果 { // 返回 json "project": { "tagline": "A query language for APIs" } } 

雖然 project 在類型系統里定義了三個字段,但我們(客戶端)只需要 tagline 這個字段,服務端就只返回這個字段,而 contributors 里的 User 和其對應字段,本次查詢(Query)並不關心。這個 demo 看似簡單,其實帶來了很多特性~

  • 強類型GraphQL與 C 和 Java 等后端語言相得益彰,服務端能對響應的形狀和性質做出一定保證,而RESTful是弱類型的,缺少機器可讀的元數據;
  • 分工GraphQL讓服務端定義好支持哪些Queries,把對數據的Query需求下放到客戶端管理,分工明確的同時保持對 API 的聚焦;
  • 分層GraphQLQuery本身是一組分層的字段,查詢就像返回的數據一樣,是一種產品(工程師)描述數據和需求的自然方式;(PS:部分翻譯的,國外好像都把產品叫做 Product Engineers 而不是 Product Manager。感覺在吐槽的樣子)
  • 預測性GraphQLQuery只返回客戶端要求的內容,沒有任何冗余(不浪費流量),而且它只有一個接口地址,由此衍生了另一個特性;
  • 兼容性:需求變動帶來的新增字段不影響老客戶端,服務端再也不需要版本號了,極大簡化了兼容問題;(App 通常是 1-2 周的固定周期發版,在原生應用不強制升級的世界里,會出現用戶 1-2 年都不升級的情況。 這意味可能同時有 52 個版本的客戶端查詢我們的服務端,而在 Fackbook 中 GraphQL API 曾支持了橫跨 3 年的移動端)
  • 自檢性GraphQL能在執行Query之前(即在開發時)提供描述性錯誤消息,在給定查詢的情況下,工具可以確保其句法是正確有效的,這使得構建高質量的客戶端變得更加容易;
  • Doc & MockGraphQL的文檔永遠和代碼同步,開發無需維護散落多處的文檔,調用者也無需擔心過期問題,而且基於類型系統的強力支撐和 graphql-tools,mocking 會變得無比容易。

GraphQL通過它的特性解決了不少問題,當然它不是沒缺點的,這個下期再聊~

我的觀點:當技術棧的缺點因其演進不再明顯之時,必是它優點大放光彩之日 。與此同時GraphQL伴隨着 graph 又帶來了很多新的思考~

GraphQL 的延伸,graphical & graph(s)

圖像天然更生動形象易於理解,這意味着GraphQL交互極強的工具和生態,比如:

  • graphiql —— A graphical interactive in-browser GraphQL IDE. 一個讓我們在瀏覽器里用圖形交互的方式探索及書寫GraphQL的 IDE。
  • graphql-voyager —— Represent any GraphQL API as an interactive graph. It's time to finally see the graph behind GraphQL! 用交互式圖表展示任意的 GraphQL API,總算能看見GraphQL背后的 graph 了!
今年 5 月 22 日 GitHub 發文宣布,去年推出的 GitHub GraphQL API 已經正式可用 (production-ready),並推薦集成商在 GitHub App 中使用最新版本的GraphQL API V4。我們可以用 graphql-voyager 探索(但因 Types、Queries、Mutations 較多數據加載略慢)。

后一個工具可把筆者驚艷壞了,想了解它的生態可以在 awesome-graphql 里尋找。通過它們,所有人都能快速閱讀查詢文檔,調試我們的查詢。

PS:主要是方便調用者和團隊新人的,不過可以思考一個問題,每天是寫代碼還是看代碼多?看接口文檔呢?

另一種思維模式 —— Thinking in graphs

圖是將很多真實世界現象變成模型的強大工具,因為它們和我們天然的心理模型和基本過程的口頭描述很相似。大家應該都沒忘在學校做的數據庫設計,筆者簡單回顧下當年手繪 E-R 圖的過程

  • 一個班級有一個班主任,1:1的關系;
  • 一個班級有多學生多個教師,1:n的關系;
  • 每個學生可以上不同的課程,n:m的關系。

OK,然后大概就成了下面這個樣子,原諒我從百度找的圖:

E-R 圖也稱實體-聯系圖(Entity Relationship Diagram),提供了表示實體類型、屬性和聯系的方法,用來描述現實世界的概念模型。
  • 真實世界的數據在本質上是分層的:今天大多數的產品開發涉及視圖層次的創建和操作,這與應用程序的結構保持一致;
  • 我們的開發模式本身也是產品需求驅動的,客戶端關注需求(怎么取、取哪些),服務端關注能力(可用性、性能),這樣的協作模式更現代更高效;
  • 數據和實體背后的本質也是關系圖:我們的服務端用對象和關系的形式處理,只不過在數據庫用扁平的表格存儲它們;(以前你可以將負責的業務數據通過導出 E-R 圖展現給同事和老板。如今你還可以通過GraphQL把到對外暴露的API也建模成一張圖。)
  • GraphQL沉淀出來的數據模型(Schema)也可以作為一種給你的團隊(后端前端客戶端甚至產品)及第三方溝通的共同語言,讓大家對這些業務領域的規則形成共同的理解,最終達成共識。

GraphQL的原理、和RESTful的優劣對比以及最佳實踐等等,未完再續~

參考資料 —— 需要FQ

來自官方的介紹:
GraphQL Introduction

GraphQL: A data query language

來自 InfoQ 的采訪:Facebook開源數據查詢語言GraphQL

來自官方的 Talks:GraphQL: Designing a Data Language

30分鍾內現場演示用Python、Ruby、Nodejs.js,設計3次 GraphQL Sever:Zero to GraphQL in 30 Minutes

 

轉載自:https://www.zhihu.com/question/264629587/answer/949588861


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM