英文原版地址:https://www.howtographql.com/...javascript
在本章中,你將瞭解GraphQL的一些基本語言結構。 內容包括,初次認識,定義類型,查詢和mutation的語法。咱們還爲你準備了一個基於graphql-up的沙箱環境,你可使用它來實驗學到的內容。java
GraphQL有本身的類型系統,用於定義API的Schema。編寫Schema的語法稱爲SDL。git
如下是使用SDL定義簡單類型Person的示例:github
type Person { name: String! age: Int! }
這個Person類型有兩個字段,name
和age
,是String和Int類型的,緊跟着的 ! 表示該字段是必需的。數據庫
能夠在類型之間相互使用。在博客應用的例子中,一個Person
能夠與一個Post
相關聯:後端
type Post { title: String! author: Person! }
同時,另外一方面,Person
類型中添加相應類型。數組
type Person { name: String! age: Int! posts: [Post!]! }
請注意,咱們剛剛建立了Person
和Post
之間的一對多關係,由於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 } }
在從服務端獲取到數據以後,主流的應用程序老是要更改存儲在後端的數據。使用GraphQL,這些更改是使用Mutation來完成的。 Mutation通常有這三種:
建立新數據
更新現有數據
刪除現有數據
Mutation遵循與查詢相同的語法結構,可是它們始終須要從Mutation
關鍵字開始。 如下是咱們如何建立一個新的Person
的例子:
mutation { createPerson(name: "Bob", age: 36) { name age } }
請注意,與以前寫的查詢相似,mutation也有一個根字段,上面的例子中,這個字段是createPerson
。 咱們以前已經講到過關於查詢參數的內容。例子中,createPerson
接受name
和age
兩個參數。
像查詢同樣,咱們還能夠爲mutation指定一個payload,咱們能夠在其中請求新建的Person對象的其餘屬性。 在咱們的例子中,咱們指定的是name
和age
,雖然咱們的例子並非頗有意義,由於咱們獲取的是咱們已知的數據。但咱們已經清晰的瞭解到,當請求是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 } }
今天,許多應用的另外一個重要需求是與服務端進行實時鏈接,以便實時響應重要事件。針對這種場景,GraphQL提供了訂閱的概念。
當客戶端訂閱了事件,它將與服務器創建一個穩定鏈接並保持住這個連接。任什麼時候刻,當有事件觸發時,服務端都會把相關信息推送到客戶端。不一樣於查詢和mutation,訂閱表明的是將數據推送出去的流的模式,而不是經典的「請求 - 響應」的模式。
訂閱使用的語法和查詢和mutation相同。咱們用來訂閱Person類型上的事件,以下所示:
subscription { newPerson { name age } }
在客戶端將此訂閱發送到服務端以後,會創建起一個連接。以後,每當mutation被執,用來建立新的Person
時,服務端就會把有關此人的信息發送給客戶端:
{ "newPerson": { "name": "Jane", "age": 23 } }
如今,你已經對查詢,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!]! }
相似地,對於createPerson
mutation,咱們必須向Mutation類型添加一個根字段:
type Mutation { createPerson(name: String!, age: String!): Person! }
請注意,根字段有兩個參數,Person的name
和age
。
最後,對於訂閱,咱們必須添加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! }