《GraphQL 名詞 101:解析 GraphQL 的查詢語法》【譯】

The Anatomy of a GraphQL Query

GraphQL 日漸成爲數據查詢的主流標準之一,整個生態圈也蓬勃發展。本文則由淺入深地詳細介紹基礎的 GraphQL 格式與關鍵字,有助於初學者對於 GraphQL 的使用造成體系認知。git

GraphQL 日漸成爲數據查詢的主流標準之一。天天都會產生許多圍繞這項技術發展的精彩討論和新工具。GraphQL最棒的特性就是提供了一個豐富語言集來描述獲取數據的API。可是用戶該如何描述這種查詢語言,以及GraphQL這項核心技術自己呢?let's talk!github

GraphQL specification解釋了幾乎全部出如今GraphQL查詢語言中的概念,可是這篇文檔實在是太長了,因此我準備在這篇博客中,藉助一些具體的栗子來闡述其中一些最重要的概念,來幫助你成爲GraphQL專家!至少在紙上談兵方面 : )數據庫

注! 這篇文章可不是GraphQL的入門讀物。首先,你應該通讀concepts on the graphql.org docs,而後經過Learn Apollo tutorial來學習使用GraphQL,最後當你想繼續深刻了解這項技術時,再回到這裏來吧!編程

最基本的GraphQL查詢

你們一般會使用「查詢」來稱呼 GraphQL API 服務的一切。可是這樣稱呼會有太多東西混雜在一塊兒了。咱們可能會把咱們跪求服務端的一系列行爲稱爲一次查詢、一次修改或者一次訂閱,但我想「請求(request)」這個詞可能更加複合HTTP通訊的概念,下面咱們先來定義一些最基礎的概念:bash

  • GraphQL 請求體: 使用GraphQL語言定義的一個或多個操做或者數據片斷,類型是字符串。
  • 操做: 能夠被GraphQL執行引擎理解的一次查詢、修改或訂閱。

爲了搞清楚GraphQL各類基本操做之間的區別,讓咱們先來看一個簡單的GraphQL請求體:服務器

GraphQL document

A simple query and its parts.

這個請求體顯示了GraphQL的主要構建塊,它指定了你嘗試獲取的數據。網絡

  • 字段(Fields):客戶端請求的數據單元,最後做爲JSON響應數據中的一個字段。請注意,它們始終稱爲「字段」,不管它們所在的層次有多深。在你的查詢中,對根節點字段的處理和最底層字段應該是同樣的。
  • 參數(Arguments):一組與特定字段關聯的鍵值對。這些參數會跟它們相關的字段一塊兒被傳遞到服務器端執行,並影響服務器對字段的處理方式。如上面的示例,參數能夠是字面量,接下來還有參數做爲變量形式的栗子。請注意,參數能夠顯示在任何字段中,即便是嵌套層次很深的字段。

爲了讓你以很是簡潔的形式定義一個GraphQL查詢,上面的栗子是GraphQL的一種很是簡單的形式。可是在GraphQL操做中三種可選的部分都沒有在上述栗子中使用。若是你不只僅是用GraphQL執行查詢操做,或是但願傳遞動態變量到GraphQL查詢中,你就須要利用到這些新的GraphQL特性。數據結構

這裏剛好有一個包含了全部可選部分的栗子:編程語言

A more detailed query and its parts.

A more detailed query and its parts.
  • 操做類型(Operation type):共三種類型:查詢(query)、更新(mutation)、訂閱(subscription)。它描述了你試圖進行何種操做。然而這些看起來意思很接近的操做,GraphQL服務器處理它們時仍是會有一些不一樣。
  • 操做名稱(Operation name):爲了方便調試和服務端打日誌,最好給你的查詢賦予語義化的命名。這樣,不管你是在網絡日誌中或者GraphQL服務器上發現錯誤,你均可以經過名字很輕鬆的在代碼庫中定位問題,而不是靠猜想(相似的工具備 Apollo Optics)。能夠把操做名稱想象成你最喜歡的編程語言中,一個語義化的函數名。
  • 變量定義(Variable definitions):當客戶端向GraphQL服務器發送查詢時,會存在查詢文檔不變,當某些字段會動態變化的狀況。這些就是查詢中的變量。由於GraphQL是靜態類型的,它能夠實時驗證你是否傳遞了正確的變量。這正是你聲明變量類型時所計劃提供的能力。

變量使用特定的序列化協議(在目前的 GraphQL 服務實現中,一般是使用JSON )經過查詢文檔獨立傳輸。下面是一個變量對象在查詢文檔中的示例: 函數

An example variables object.

An example variables object.
能夠看到,這裏的關鍵是變量名稱須要與變量定義所匹配,其名稱是`Episode`枚舉中的一個成員。
  • 變量(Variables): 它是傳遞給GraphQL operation的值的字典,提供了operation的動態入參。

這裏有一個在談及Graph的技術意義時很重要,卻不常被說起的核心概念——花括號之間的全部東西叫什麼?

*選擇集(selection set)*是一個會在GraphQL 文檔中常常出現的概念,它賦予了GraphQL遞歸的特性,容許你獲取嵌套形式的數據。

  • 選擇集(selection set):它是一次operation中須要的一組字段,或者被嵌套在其餘的字段中。GraphQL查詢必須包含一個標識選擇集的字段,且該字段返回的是對象類型,選擇集不能設置在返回值是標量類型(Scalar Types)的字段上,例如Int或者String

片斷(Fragments)

當開始介紹片斷(fragments)以後,GraphQL 將變得更增強大。它帶來了一系列新的概念。

  • 片斷定義(Fragment definition):定義一個片斷是GraphQL文檔的一部分。爲了區別於咱們下面會介紹的內聯片斷,它有時候也被稱爲片斷命名

Fragments

A fragment definition and its parts.
  • **片斷名稱(Fragment name): **片斷(fragments )名在GraphQL文檔中必須是惟一的。這個名稱用於在操做(operations)或者其餘片斷(fragments )引用片斷(fragments )。就像操做(operations)名稱同樣,片斷名也能用於服務端日誌調試,因此咱們推薦使用明確且有意義的片斷(fragments )名。若是你使用了正確的片斷(fragments )名,在優化數據獲取時,你可以很好的追蹤你的代碼。
  • 類型條件(Type condition): GraphQL操做老是開始於查詢、修改或者訂閱schema中的類型,可是片斷(fragments )可以用於任一選擇,因此爲了將校驗片斷(fragments )與校驗schema獨立開,你須要指定片斷(fragments )可以使用的類型,而這就是類型條件(Type condition)的做用。

就像操做(operations)同樣,片斷也選擇集,使用起來也跟在操做(operations)中使用選擇集同樣。

在你的操做(operations)中使用片斷(fragments )

片斷(fragments )只有在操做(operations)中使用才能發揮出做用。片斷是 GraphQL 的主要組合數據結構,經過片斷能夠重用重複的字段選擇,減小 query 中的重複內容。接下來咱們將介紹使用片斷(fragments )的兩種方式:

fragments

  • **片斷擴展運算符(Fragment spread): ** 當你在操做或者其餘片斷中使用片斷時,你能夠將片斷名置於...以後來表示片斷。例如沒有片斷時須要這樣編寫 query:
query noFragments {
  user(id: 4) {
    friends(first: 10) {
      id
      name
      profilePic(size: 50)
    }
    mutualFriends(first: 10) {
      id
      name
      profilePic(size: 50)
    }
  }
}
複製代碼

query 中存在下列重複的選擇集合:

{
  id
  name
  profilePic(size: 50)
}
複製代碼

能夠用片斷簡化爲:

query withFragments {
  user(id: 4) {
    friends(first: 10) {
      ...friendFields
    }
    mutualFriends(first: 10) {
      ...friendFields
    }
  }
}

fragment friendFields on User {
  id
  name
  profilePic(size: 50)
}
複製代碼

使用片斷時須要加上 ... 操做符表示展開片斷內容,這稱爲片斷擴展運算符(fragment spread),它能夠用在任何選擇集(selection set)中,用以匹配片斷的類型條件。

  • 內聯片斷(Inline fragment): 若是你僅僅是想執行一些依賴結果類型的字段,卻不想把它們抽離成獨立的定義,你可使用內聯片斷( inline fragment)。它使用起來跟獨立的命名片斷同樣,可是寫在查詢的內部。有一點不一樣的是,對於內聯片斷來講類型條件(type condition)不是必須的,能夠像使用指令同樣來使用它,接下來咱們會演示指令(directive)的栗子。

指令(Directives)

指令是獨立於GraphQL server以外的一個附加功能。指令不會對結果的值產生影響,可是會影響哪些結果會被返回,也許還會影響這些結果是如何被執行的。指令能夠出如今查詢的任何地方,但在這篇文章中咱們只關注當前GrahpQL文檔所描述的skip(忽略)include(包括) 兩個指令。

Directives

You probably wouldn’t usually put all of these in one query, but it’s the easiest way to demonstrate.
你能在上文廚房水槽的栗子中使用指令`skip` 和 `include`。`include` 指令表示只有在 if 參數爲 true 時才引入片斷表示的字段。`skip` 指令表示在 if 參數爲 true 時忽略片斷中的字段。因爲指令的語法至關靈活,咱們能夠利用它來給GraphQL添加更多的特性,而不是使用語法解析或者引入更復雜的工具的方式。
  • **指令(Directive): ** 在字段、片斷或者查詢中的一個註釋,include 指令表示只有在 if 參數爲 true 時才引入片斷表示的字段。skip 指令表示在 if 參數爲 true 時忽略片斷中的字段。
  • 指令參數(Directive arguments): 與字段參數相似,只不過它們是被執行引擎處理,而不是傳遞給字段解析器(field resolver)。

總結

GraphQL 是在應用層對業務數據模型的抽象,是對數據請求定製的 DSQL,它解除了接口和數據之間的綁定,對業務數據結構作了抽象和整理,業務邏輯中的數據依賴於底層數據庫結構,而且能夠由具體業務場景來定製,不一樣的業務場景只要基於一樣一套基礎業務數據模型就能夠獲得複用,在我看來,這纔是 GraphQL 帶來的最大改變和收益。 目前GitHub整站API已遷移GraphQL,淘寶也在生成環境有所實踐。

參考文檔:


《IVWEB 技術週刊》 震撼上線了,關注公衆號:IVWEB社區,每週定時推送優質文章。

相關文章
相關標籤/搜索