天天看點

Graphql入門

早在2012年,Facebook認為人們隻有在離開PC的時候才會用智能手機,很快他們就發現這個認識是多麼的錯誤!于是Facebook把注意力從Web移到了智能終端上。在那個時候,他們嚴重的依賴于RESTful API。大量的并發請求和對補充資料的二次請求給他們造成了很大的麻煩,尤其是響應時間。一個解決方案是設計足夠多的資源來滿足單次的請求。但是,這造成了服務端的擴充和維護困難。

在尋找更好的解決方案的過程中,Facebook的工程師發現開發人員不應該先入為主的把資料看成RESTful一樣的集合。如何更好地存儲和擷取資料不應該是他們要主要考慮的内容。他們應該更多的考慮資料的關系,網狀的關系。

在這個情況下GraphQL應運而生。

一個GraphQL查詢可以包含一個或者多個操作(operation),類似于一個RESTful API。操作(operation)可以使兩種類型:查詢(Query)或者修改(mutation)。我們看一個例子:

你的第一印象:“這個不是JSON?”。還真不是!就如我們之前說的,GraphQL設計的中心是為用戶端服務。GraphQL的設計者希望可以寫一個和期待的傳回資料schema差不多的查詢。

注意上面的例子有三個不同的部分組成:

<code>client</code>是查詢的operation

<code>(id: 1)</code>包含了傳入給Query的參數

查詢包含<code>id</code>和<code>name</code>字段,這些字段也是我們希望查詢可以傳回的

我們看看server會給這個查詢傳回什麼:

就如我們期望的,server會傳回一個JSON串。這個JSON的schema和查詢的基本一緻。

我們再看看另一個例子:

這次我們查詢<code>products</code>,并傳入兩個參數:<code>product_category_id</code>用于過濾,一個指明按照<code>price</code>字段降序排列。查詢中包含的字段是:<code>name</code>、<code>shell_size</code>、<code>manufacturer</code>和<code>price</code>)。

你可能已經猜到傳回的結果是什麼樣子的了:

從這幾個初級的例子裡你可以看出來GraphQL允許用戶端明确指定它要的是什麼,避免了資料後去的備援或者不足。和RESTful API對比一下,每一個用戶端都會對應很多個RESTful API或者一個API要服務很多個用戶端。是以說GraphQL是很好的查詢語言。所有的operation、參數和所有可以查詢的字段都需要在GraphQL server上定義、實作。

GraphQL還解決了另外一個問題。假設我們要查詢<code>product_categories</code>和相關的<code>products</code>。在一個RESTful server上你可以實作一個API,傳回全部的資料。但是,大多數的情況下,用戶端會先請求<code>product_categories</code>之後在其他的請求中擷取相關的某些<code>products</code>。

我們看看使用GraphQL可以怎麼做:

我們這一次沒有使用參數。在查詢中我們指定了我麼需要每一個<code>product_category</code>的<code>name</code>,還有所有的這個類别下的産品,每個産品的字段也都分别指定。傳回的結果:

查詢的嵌套沒有限制,全看我們的查詢和server的實作。比如西面的例子完全合法:

這裡我們請求server傳回某個客戶的<code>purchases</code>。查詢裡不僅指定了<code>purchase</code>的字段,還指定了相關的<code>product</code>,<code>product_category</code>的名稱。

也就是說,你可以查詢值類型:<code>Int</code>, <code>Float</code>, <code>String</code>, <code>Boolean</code>和<code>ID</code>。

而上例中的<code>purchase</code>裡的字段,<code>product</code>、<code>client</code>和<code>product_category</code>都是對象類型(Object Type)的。這些類型都需要我們自己定義。

由于GraphQL查詢都是結構化的,資訊也是類樹結構展示的。值類型(Scalar Type)的可以了解為葉子,對象類型(Object Type)可以了解為樹幹。

在GraphQL查詢中可以為Operation裡的字段指定别名。比如查詢裡指定了字段<code>cymbal_size</code>,但是用戶端隻能接受<code>diameter</code>。另外查詢的傳回結果都包含在以operation名稱為key的對象裡,是以這個名稱也可以設定一個别名:

傳回的資料:

現在,用戶端APP要擷取另個分開的list: <code>drum sets</code>和<code>cymbals</code>。在GraphQL裡你不會被限制在一個operation裡。同時我們也可以像設定字段别名那樣設定傳回結果的别名:

你可能已經注意到,在查詢的兩個對象中都包含了字段:<code>id</code>、<code>name</code>、<code>manufacturer</code>、<code>price</code>。

為了避免重複字段,我們可以使用GraphQL提供的Fragments。我們來把重複的字段都提出來,放到一個fragment裡:

要使用一個Fragment就使用操作符:<code>...</code>。

我們要減少查詢語句中的重複,我們來看看另外的一個例子該如何處理:

我們使用兩個operation查詢server,并且每個都包含了<code>client_id</code>參數。如果可以把這個集中到一起就非常好了。我們可以使用GraphQL的變量來實作這個效果。我們來添加一個<code>clientID</code>變量。

我們在operation的前面定義了變量,然後我們就可以在整個查詢中使用這個變量了。 為了使用變量的定義,我們需要在查詢的時候附帶變量值的JSON。

當然,我們也可以指定一個預設值:

GraphQL不僅可以用來查詢資料,也可以建立、更新和銷毀資料。當然和查詢一樣,這些也需要server端有對應的實作。增、删、改一類的operation在GraphQL裡統稱為Muration(修改)。我們就通過幾個例子來示範一下mutation。

我們現在指定operation的類型為mutation,而不是query。在<code>create_client</code>操作裡我們傳入了建立一個<code>client</code>需要的資料,并最終傳回一個查詢集合:

上面的資料有一點錯誤,生日不對。下面就來用更新來fix這個錯誤:

最後,如果我們要删除這個資料可以這樣:

注意:<code>create_client</code>、<code>update_client</code>和<code>destroy_client</code>這些operation都是在GraphQL server實作好的。如果有什麼方法可以知道GraphQL server都實作了什麼方法不是很好,是的有GraphQL的doc可以檢視。

GraphQL的一個非常好的特性就是,它會根據已經定義好的類型系統來自動生成出一個說明文檔。這樣你就不用一次一次的翻看代碼,而直接檢視文檔來了解operation的全部實作細節。如果你用的是<code>express-graphql</code>, 并設定<code>graphiql</code>為<code>true</code>的話,那麼就會生成一個web的調試界面。在最右側可以直接使用doc:

或者,也可以使用對于應定義好的schema的查詢,如:

結果為:

對于<code>mutation</code>類型的操作也是一樣的:

查詢的結果為:

就像上文展示的一樣,你還可以查詢很多其他的内容。比如:

我們來簡單的看看結果是什麼樣的:

你會看到server實作了一個<code>clients</code>的查詢operation,參數為<code>ids</code>、<code>name</code>和<code>dob</code>。第二個操作是<code>products</code>,在這裡的參數是<code>ids</code>、<code>product_category_id</code>和<code>order</code>、<code>limit</code>。

歡迎加群互相學習,共同進步。QQ群:iOS: 58099570 | Android: 572064792 | Nodejs:329118122 做人要厚道,轉載請注明出處!

本文轉自張昺華-sky部落格園部落格,原文連結:http://www.cnblogs.com/sunshine-anycall/p/6357577.html,如需轉載請自行聯系原作者