[譯] 怎樣使用GraphQL - 3.核心概念

英文原版地址:https://www.howtographql.com/...javascript

在本章中,你將瞭解GraphQL的一些基本語言結構。 內容包括,初次認識,定義類型,查詢和mutation的語法。咱們還爲你準備了一個基於graphql-up的沙箱環境,你可使用它來實驗學到的內容。java

視圖定義語言(SDL)

GraphQL有本身的類型系統,用於定義API的Schema。編寫Schema的語法稱爲SDL。git

如下是使用SDL定義簡單類型Person的示例:github

type Person {
  name: String!
  age: Int!
}

這個Person類型有兩個字段,nameage,是String和Int類型的,緊跟着的 ! 表示該字段是必需的。數據庫

能夠在類型之間相互使用。在博客應用的例子中,一個Person能夠與一個Post相關聯:後端

type Post {
  title: String!
  author: Person!
}

同時,另外一方面,Person類型中添加相應類型。數組

type Person {
  name: String!
  age: Int!
  posts: [Post!]!
}

請注意,咱們剛剛建立了PersonPost之間的一對多關係,由於Person上的posts字段其實是一個帖子數組。服務器

使用查詢語句獲取數據

使用REST API時,會從指定接口加載數據。每一個接口都明肯定義了返回的數據結構。這意味着客戶端須要的數據,已經在URL中制定好了。數據結構

GraphQL中採用的方式大相徑庭。GraphQL的API一般只暴露一個接口,而不是返回固定數據結構的多個接口。 這是由於返回的數據結構不是一成不變的,而是靈活的,讓客戶端來決定真正須要的是什麼數據。post

這意味着客戶端須要向服務端發送更多信息來告知所需求的數據 - 這個額外信息稱爲查詢。

基本查詢

咱們來看看客戶端發送給服務端的簡單查詢示例:

{
  allPersons {
    name
  }
}

在這查詢中,allPersons字段稱爲查詢的根字段。根字段以後的全部內容稱爲查詢的payload。此查詢中,指定的惟一payload字段是name

此查詢將返回當前存儲在數據庫中的全部的人員列表。返回的示例以下:

{
  "allPersons": [
    { "name": "Johnny" },
    { "name": "Sarah" },
    { "name": "Alice" }
  ]
}

請注意,每一個Person在響應結果中只有name一個屬性,服務端並無返回age屬性。 這正是由於name是在查詢中指定的惟一字段。

若是客戶端也想要獲取年齡屬性,那麼要作的,僅僅是調整一下查詢語句,在查詢的payload中加入新的字段:

{
  allPersons {
    name
    age
  }
}

GraphQL的一個重要優點是,容許直接經過嵌套的方式查詢信息。例如,若是想獲取一個Person寫的全部posts,能夠簡單地按照類型的結構來獲取數據:

{
  allPersons {
    name
    age
    posts {
      title
    }
  }
}

查詢時帶上參數

在GraphQL中,每一個在視圖中定義的字段均可以擁有參數(零或多個)。例如,allPersons字段能夠包含last參數,用來返回特定數量的Persons。相應的查詢以下:

{
  allPersons(last: 2) {
    name
  }
}

經過Mutation操做數據

在從服務端獲取到數據以後,主流的應用程序老是要更改存儲在後端的數據。使用GraphQL,這些更改是使用Mutation來完成的。 Mutation通常有這三種:

  • 建立新數據

  • 更新現有數據

  • 刪除現有數據

Mutation遵循與查詢相同的語法結構,可是它們始終須要從Mutation關鍵字開始。 如下是咱們如何建立一個新的Person的例子:

mutation {
  createPerson(name: "Bob", age: 36) {
    name
    age
  }
}

請注意,與以前寫的查詢相似,mutation也有一個根字段,上面的例子中,這個字段是createPerson。 咱們以前已經講到過關於查詢參數的內容。例子中,createPerson接受nameage兩個參數。

像查詢同樣,咱們還能夠爲mutation指定一個payload,咱們能夠在其中請求新建的Person對象的其餘屬性。 在咱們的例子中,咱們指定的是nameage,雖然咱們的例子並非頗有意義,由於咱們獲取的是咱們已知的數據。但咱們已經清晰的瞭解到,當請求是mutation時,也可以指定查詢信息,這體現了mutation的強大之處,容許在一次請求來回中,從服務器獲取新數據!

上面的mutation的響應數據是這樣的:

"createPerson": {
  "name": "Bob",
  "age": "36",
}

咱們老是能瞭解到,當新增數據時,GraphQL會在服務端生成一個惟一的ID類型。擴展一下咱們以前定義的Person類型,咱們能夠添加一個id字段,以下所示:

type Person {
  id: ID!
  name: String!
  age: Int!
}

如今,當建立一個新的Person時,能夠直接在mutation的payload中查詢id,這是事先在客戶端不知道的信息:

mutation {
  createPerson(name: "Alice", age: 36) {
    id
  }
}

使用Subscription進行實時更新

今天,許多應用的另外一個重要需求是與服務端進行實時鏈接,以便實時響應重要事件。針對這種場景,GraphQL提供了訂閱的概念。

當客戶端訂閱了事件,它將與服務器創建一個穩定鏈接並保持住這個連接。任什麼時候刻,當有事件觸發時,服務端都會把相關信息推送到客戶端。不一樣於查詢和mutation,訂閱表明的是將數據推送出去的的模式,而不是經典的「請求 - 響應」的模式。

訂閱使用的語法和查詢和mutation相同。咱們用來訂閱Person類型上的事件,以下所示:

subscription {
  newPerson {
    name
    age
  }
}

在客戶端將此訂閱發送到服務端以後,會創建起一個連接。以後,每當mutation被執,用來建立新的Person時,服務端就會把有關此人的信息發送給客戶端:

{
  "newPerson": {
    "name": "Jane",
    "age": 23
  }
}

定義視圖(Schema)

如今,你已經對查詢,mutation和訂閱有一個基本的瞭解,讓咱們將這些放在一塊兒,學習如何編寫一個視圖,讓你本身執行目前爲止全部的示例。

視圖是使用GraphQL API時最重要的概念之一。它指定了API的功能,並定義了客戶端如何請求數據。它一般被視爲服務器和客戶端之間的協議。

一般,視圖只是GraphQL類型的集合。 可是,在爲API編寫視圖時,有一些特殊的根類型:

type Query { ... }
type Mutation { ... }
type Subscription { ... }

查詢,mutation和訂閱是客戶端發送請求的入口點。要啓用咱們前面看到的allPersons查詢,查詢類型必須以下定義:

type Query {
  allPersons: [Person!]!
}

allPersons稱爲API的根字段。再考慮到,咱們將last參數添加到allPersons的示例,咱們必須以下定義Query:

type Query {
  allPersons(last: Int): [Person!]!
}

相似地,對於createPersonmutation,咱們必須向Mutation類型添加一個根字段:

type Mutation {
  createPerson(name: String!, age: String!): Person!
}

請注意,根字段有兩個參數,Person的nameage

最後,對於訂閱,咱們必須添加newPerson根字段:

type Subscription {
  newPerson: Person!
}

將全部整合在一塊兒,這是你在本章中看到的全部查詢和mutation的完整模式:

type Query {
  allPersons(last: Int): [Person!]!
}

type Mutation {
  createPerson(name: String!, age: String!): Person!
}

type Subscription {
  newPerson: Person!
}

type Person {
  name: String!
  age: Int!
  posts: [Post!]!
}

type Post {
  title: String!
  author: Person!
}
相關文章
相關標籤/搜索