一、GraphQL簡介 1、什麼是GraphQL? GraphQL官網:https://graphql.org/,這個是英文的,https://graphql.js.cool/這個是中文的。 GraphQL是一種用於API的查詢語言。GraphQL 既是一種用於 API 的查詢語言也是一個滿足你數據 ...
一、GraphQL簡介
1、什麼是GraphQL?
GraphQL官網:https://graphql.org/,這個是英文的,https://graphql.js.cool/這個是中文的。
GraphQL是一種用於API的查詢語言。GraphQL 既是一種用於 API 的查詢語言也是一個滿足你數據查詢的運行時。 GraphQL 對你的 API 中的數據提供了一套易於理解的完整描述,使得客戶端能夠準確地獲得它需要的數據,而且沒有任何冗餘,也讓 API 更容易地隨著時間推移而演進,還能用於構建強大的開發者工具。
GraphQL與資料庫、存儲技術和開發語言、框架無關。GraphQL的服務也不限定使用的傳輸技術,但是通長是使用HTTP(S)來傳輸。
嵌套查詢,查詢是可以嵌套的,一次請求,獲得多個類型的數據,無需繼續鑽取數據,客戶端不會收到不需要的數據屬性。
每當對GraphQL伺服器進行查詢的時候,都會使用類型系統進行驗證。
在Schema里定義類型:
GraphQL通長被稱作是“聲明式數據獲取語言”。
GraphQL的設計原則:
層次結構性、以產品為中心、強類型、客戶端定製查詢、內省(Introspective)
2、GraphQL的歷史
源自Facebook,2012年Facebook開始開發,2015年開源
3、GraphQL和REST
至於REST的一些概念,開源參考一下之前的一篇隨筆,點擊這裡
前面提到GraphQL可以理解為基於RESTful的一種封裝,目的在於構建使Client更加易用的服務,可以說GraphQL是更好的RESTful設計。在過去的十多年中,REST已經成為設計web api的標準(雖然只是一個模糊的標準)。它提供了一些很棒的想法,比如無狀態伺服器和結構化的資源訪問。然而REST api表現得過於僵化,無法跟上訪問它們的客戶的快速變化的需求。 GraphQL的開發是為了應付更多的靈活性和效率,它解決了與REST api交互時開發人員所經歷的許多缺點和低效之處。 為了說明在從API獲取數據時REST和GraphQL之間的主要區別,讓我們考慮一個簡單的示例場景:在blog應用程式中,應用程式需要顯示特定用戶的文章的標題。同一屏幕還顯示該用戶最後3個關註者的名稱。REST和GraphQL如何解決這種情況?
使用REST API來現實時,我們通常可以通過訪問多次請求來收集數據。比如在這個示例中,我們可以通過下麵的三步來實現:
1、 通過 /user/<id>獲取初始用戶數據
2、 通過/user/<id>/posts 返回用戶的所有帖子
3、 請求/user/<id>/followers,返回每個用戶的關註者列表
調用關係如下圖所示:
如果用GraphQL的話,我們只需要一次請求就可以完成上述的需求:
在GraphQL的世界里我們不用多取數據,也不用擔心數據取少了,我們只需要按需獲取即可。
REST最常見的問題之一是API的返回數據過多或者過少,這是因為客戶端下載數據的唯一方法是通過訪問返回固定數據結構的endpoint,這就會導致我們設計API非常困難,因為它既要能夠為客戶提供精確的數據需求,又需要滿足不同調用者的需求,這本身就是相互矛盾的。GraphQL的發明者Lee Byron提出了一個很重要的概念: “用圖形來思考,而不是endpoint”。
可以使用GraphQL管理REST端點
GitHub的API有四個版本,第三個版本使用REST,第四個就是用的GraphQL。https://developer.github.com/v4/explorer/
二、圖論(GraphQL Theory)
圖論就是研究圖的,圖開源用來表示一組關聯的對象。可以把圖看作是一個包含數據點和連接的對象。例如:人機關係圖、家譜、公交線路圖
這是一個無序圖,一個圖包含:
1、頂點Vertices
2、邊Edge
3、G=(V,E)
G:圖
V:頂點
E:邊
上圖中:
Vertices={1,2,3,4}
Edge={{1,2},{1,3},{1,4,},{2,4},{3,4}}
有向圖:
有向圖的邊有箭頭
Vertices={1,2,3,4}
Edges=({1,2},{1,3},{3,4})
Graph=({1,2,3,4},{1,2},{1,3},{3,4})
當有向圖的序對改變了,圖就變了
圖就變成了Graph=({1,2,3,4},{4,3},{3,1},{1,2})
樹形圖也是圖,比如HTML的結構、二叉樹
三、Query(查詢)&Mutation(修改)
這裡是Git上面的一個API,可以進行簡單的使用https://developer.github.com/v4/explorer/,需要先登錄才可以。
1、GraphQL VS SQL
SQL查詢資料庫;GraphQL查詢API
SQL的數據存在數據表裡;GraphQL的數據可以存放在任何地方
SQL使用SELECT查詢數據;GraphQL使用Query
SQL使用INSERT、UPDATE、DELETE來修改數據;GraphQL使用Mutation修改數據
GraphQL還可以進行訂閱(通過socket)
2、查詢Query
GraphQL的請求,GraphQL查詢的內容通過HTTP POST的Body發送給GraphQL端點。
查詢就是從API獲取數據,它表示了你想從GraphQL伺服器獲取的數據;通過欄位(field)來請求查詢的數據;這些欄位和查詢結果的JSON響應的欄位對應。
GraphQL查詢錯誤:
成功查詢的JSON結果裡面包含一個data欄位,不成功的查詢結果裡面包含一個errors欄位,裡面有具體的錯誤信息。JSON相應結果可同時包data和errors欄位。
errorTest這個地段是吧存在的,所以在後面會包含一個errors欄位,裡面有具體的錯誤信息。
Query是GraphQL的一個類型,叫做根類型,因為它映射的事一個操作,而操作則代表著查詢文檔的根節點。
查詢可用的欄位是在schema裡面定義的;可用查看文檔
使用ALT+Space,可用顯示參數
GraphQL修改和查詢很像,就是意圖不同。
GraphQL欄位類型:
Scalar Type:Int、String、Float、Boolean、ID
Object Type
GraphQL片段Fragments
Fragments就是可用服用的選擇集
片段(Fragments):
假設我們的app有比較複雜的頁面,講正反派主角及其友軍分為兩撥。你立馬就能想到對應的查詢會變得複雜,因為我們需要將一些欄位重覆至少一次——兩房各一次作比較。
這就是為何GraphQL包含了稱作片段的可復用單元,片段使你能夠阻止一組欄位,然後在他們需要的地方引入,下麵的例子展示瞭如何使用片段解決上述場景:
GraphQL聯合類型Union Type
如果你想返回不止一種類型,那麼您可以使用Union Type
GraphQL介面Interface
2、修改Mutation
Mutation也是根對象類型,Mutation和Query很像,有名字、可以有返回的選擇集,不同之處就是Mutation會修改後臺數據的狀態。
GraphQL查詢變數:
代替寫死的參數值,可以動態賦值,使用$開頭。
3、訂閱Subscription
Subscription允許我們監聽GraphQL API的實時數據變化,Subscription也是根類型,通過WebSocket,與Query和Mutation不同,Subscription保持鏈接打開狀態,如果想停止監聽,需要取消訂閱。
4、內省Introspection
一個非常強大的特性,Introspection可以讓你查詢當前API的schema,查詢可用類型:_schema,查詢類型明細:_type
5、抽象語法樹Abstract Syntax Trees
抽象語法樹AST,查詢文檔是字元串,查詢時被解析成AST,併在每個操作運行前進行嚴重,AST是要給層次結構的對象,代表了查詢,每一個操作都會被解析成AST(很重要)
四、Schema和Types
1、Schema是什麼
GraphQL會改變你進行設計的過程,使用REST的時候,可以把你的API看作是一組REST端點,而在GraphQL里你把你的API看作成是一組類型,為你暴露的API定義的這組數據類型就叫做Schema。
設計Schema:
Schema First:使前後端團隊在數據類型上保持一致
GraphQL使用SDL(Schema Definition Language)語言來定義Schema,無論使用什麼開發語言或者框架GraphQL的SDL都是一樣的,GraphQL的Schema就是定義了可用類型的文本文檔,它被客戶端和伺服器端來驗證GraphQL請求。
2、定義Types
GraphQL Schema的核心就是類型(Type),一個類型代表著一個自定義的對象,而這些對象則代表 了你的核心特征,類型有欄位(Field),它代表了關聯每個對象的數據,每個欄位都會返回一個特定的數據類型。Schema就是類型定義的集合,Schema定義文件的尾碼名通常是.graphql
類型定義:
例子:嘆號表示不能為null
Scalar Type標量類型:
內置Int、Float、String、Boolean、ID
可以自定義Scalar Type,Scalar Type不是對象類型,它沒有欄位,例如:
Enum枚舉類型:
枚舉類型也是標量類型,它可以返回一組字元串中的一個值,例如:
3、Connections和List
創建Schema時,可以定義返回一個由任意Graph類型組成的列表,例如:[String]、[User],列表頁可以由不同的類型組成,使用Union Type或者Interface Type,[Int]、[Int!]、[Int]!、[Int!]!的區別
一對一連接
圖論里,兩個對象之間的連接叫做邊(Edge),而由一個對象連接到另外一個對象的連接就是一對一的連接
一對多連接
要儘量報紙GraphQL服務的無向性,也就是說可以從圖的任何一個定點開始遍歷;針對上例,添加一條從User類型回到Photo的路徑:
多對多連接
例如標簽操作Tagging
多對多連接,需要在雙方類型里都添加List欄位,一個多對多連接由兩個一對多連接組成
創建多對多連接時,由時需要保存關係本身,這時就需要通過類型(Through Type),把邊(Edge)定義為一個自定義對象類型,相當於連接兩個節點的節點。由不同類型組成邊的列表,GraphQL里的列表不一定非得是同一種理性,使用Union Type,Interface結合Fragment可以達到此目的。
Union Type
Union Type,我們可以用它返回多種類型中的一種類型
Interface:
為了保證某些類型必須包含特定的欄位,我們可以使用介面Interface
4、Arguments參數
GraphQL里的任何欄位都可以由Arguments,Arguments必須有類型,這個類型應該是hischema中已經定義好的標量類型或者對象類型
過濾數據:
Arguments吧一定非得是費控的,使用可控欄位可以添加可選參數(optional arguments/optional parameters)
翻頁;
要實現翻頁功能至少需要兩個可選參數(optional arguments),首先需要設定當前頁一次性返回的條目數(first、pageSize.....),然後還要設定從哪個位置開始獲取這些數據(start,pageIndex......)
排序:
方法有很多,可以使用enum來決定哪個欄位可以用來排序
5、Mutation修改
Mutation也在schema裡面定義,技術上Mutation和Query沒有區別,只是他們的意圖不同,Mutation是用來修改狀態的,Mutation的名稱里應該包含動詞。
6、Input Types輸入類型
Query和Mutation的參數可能會很多,這時最好使用Input Type來整理單數(arguments),Input Type和GraphQL里的對象類型很像,但是它只能用作輸入參數,Input Type可以用作於任何子墩
7、Return Types返回類型
Schema里所有的欄位都可以返回定義好的主類型,但有時候需要返回一些關於查詢和修改的元信息,這時就可以創建一個返回類型。
8、Subscription訂閱
Subscription類型和GraphQL的SDL里的其他類型也沒有什麼區別,在自定義對象類型的子墩上定義可用的Subscriptions。Subscription可用有參數
9、Schema文檔
編寫Schema的時候,可以為每個欄位添加一些描述