作者: 一字馬胡
轉載標志 【2017-11-13】
更新日志
日期 | 更新內容 | 備注 |
---|---|---|
2017-11-13 | 新建文章 | 初版 |
導入
作為一種強大的DSQL橘券,學習GraphQL的意義是非常大的,為了迅速了解GraphQL哪雕,可以參考文章GraphQL初探:一種強大的DSQL琼腔,該文章給出了一個使用GraphQL的簡單示例demo抡诞。GraphQL不僅可以面向傳統(tǒng)的數(shù)據(jù)庫(比如Mysql适刀,NoSql)秤朗,還可以面向微服務,以及其他的數(shù)據(jù)源笔喉,或者面向數(shù)據(jù)庫取视、微服務等混合數(shù)據(jù)源硝皂,GraphQL試圖抽象服務端的數(shù)據(jù)成為一個綜合的數(shù)據(jù)庫,而前端(客戶端)的請求就是查詢數(shù)據(jù)庫作谭,這樣做很明顯的一個好處是前端(客戶端)可以根據(jù)自己的需要來查詢(就像是請求mysql數(shù)據(jù)庫稽物,只輸出需要的列),這稱為“精準查詢”折欠,使用GraphQL的另外一個明顯的好處是一次請求即可獲取所需要的數(shù)據(jù)贝或,對于請求REST API來說,每次請求返回的數(shù)據(jù)格式是相對固定的怨酝,沒有太多的靈活性傀缩,并且可能為了將接口變薄那先,會根據(jù)數(shù)據(jù)屬性等將接口拆分開來农猬,所以每個接口可能只能返回一部分需要的內容,所以就需要客戶端來請求多次來獲取到所有的數(shù)據(jù)售淡,這樣就造成了一些延時斤葱。下面的圖片展示了GraphQL如何將多種數(shù)據(jù)源組合起來為前端(客戶端)提供統(tǒng)一的API(使用GraphQL來設計API只需要提供一個端點):
本文依然不會對GraphQL的原理做太多分析總結,學習需要一步一步來揖闸,上一篇文章僅僅寫了一個可運行的demo揍堕,本文想要借助現(xiàn)有的實現(xiàn)來更加深入的了解一些關于GraphQL的內容,為后面可以自主設計GraphQL API提供支持汤纸。Github 的V4 API借助了GraphQL來設計衩茸,具有很高的研究價值,所以本文就介紹Github 的V4 API贮泞,并且介紹如何使用V4接口來從Github的服務器獲取我們想要的數(shù)據(jù)楞慈,因為Github V4 API只提供了一個端點:https://api.github.com/graphql,所以很大程度上降低了我們的認知障礙啃擦,并且Github提供了在線查詢界面:Github V4 API Explorer囊蓝,你可以在左側的輸入框中輸入GraphQL查詢語句,點擊執(zhí)行就可以在右側看到執(zhí)行結果令蛉,非常直觀,并且提供了完整的接口文檔,可以獲取任意我們想要獲取的數(shù)據(jù)添怔,本文將首先介紹一些Github V4 API中的新概念虎眨,然后基于Github V4 API Explorer來介紹如何獲取我們想要的數(shù)據(jù)。
Github V4 API中的一些新概念
Schema
首先是Schema祷安,在GraphQL中Schema是一個很重要的概念夫啊,Schema定義了GraphQL API的類型系統(tǒng),它完整的描述了前端(或者客戶端)可以從服務端獲取的所有數(shù)據(jù)內容辆憔,前端或者客戶端的GraphQL查詢請求將根據(jù)Schema進行校驗和執(zhí)行撇眯,客戶端可以通過“自省”(introspection)獲取關于schema的信息报嵌。schema存放于GraphQL API服務器。關于如何生成一個schema可以參考本文開篇的文章鏈接熊榛。
Field
Field是客戶端可以從服務端獲取的某個內容锚国,比如某個字段,或者某個對象等玄坦,GraphQL查詢語言本質上就是從對象中選擇field血筑,所有的GraphQL操作必須指明到最底層的field,并且返回值為標量煎楣,以確保響應結果的結構明白無誤豺总,所謂標量(scalar),也就是基本數(shù)據(jù)類型择懂,比如String喻喳、int等。如果你嘗試返回一個不是標量的field困曙,schema校驗將會拋出錯誤表伦。你必須添加嵌套的內部field直至所有的field都返回標量,這一點很重要慷丽,需要牢牢記住蹦哼。
Connection
還記得GraphQL的標志嗎?它是一個圖要糊,由頂點和邊構成纲熏,所謂Connection,就是可以關聯(lián)查詢锄俄,GraphQL就是通過Connection來實現(xiàn)只需要一次請求就可以獲取全部需要的數(shù)據(jù)的功能的局劲,客戶端可以通過Connection來進行關聯(lián)查詢,比如在查找一篇文章的信息的時候珊膜,除了文章的標題容握、作者、文字內容车柠、圖片內容剔氏、閱讀數(shù)等信息外,可以通過Connection查詢該文章下面的評論信息竹祷,而在評論中谈跛,可以通過Connection根據(jù)評論人的id來獲取用戶的信息,這就是Connection的威力塑陵,下文中將會把Connection的威力體現(xiàn)出來感憾。
Edge
Edge是GraphQL中的邊,它表示Node之間的Connection令花,當你查詢一個connection時阻桅,你通過edge到達node凉倚。每個edgesfield都有一個nodefield和一個cursorfield。cursor是用來分頁的嫂沉。
Node
Node是一個對象稽寒,它就是我們獲取數(shù)據(jù)的節(jié)點,比如用戶信息的對象就是一個節(jié)點趟章,或者一篇文章的信息就是一個節(jié)點杏糙,如果正在查詢的Node不是標量的話,那么我們需要指定Node中的Field直到返回的是標量類型為止蚓土。
Github V4 API實戰(zhàn)
上文中介紹了一些關于Github V4 API的相關內容宏侍,本文剩下的部分將清楚明白的介紹如何使用Github V4 API來獲取我們想要的數(shù)據(jù),通過本文的介紹蜀漆,你應當很清晰的認識到GraphQL帶來的福利谅河,以及Github V4 API為何要選擇GraphQL來進行設計。首選嗜愈,你需要打開Github V4 API Explorer旧蛾,下面的圖片展示了你應當看到的界面:
左側是GraphQL查詢語句的輸入框莽龟,中間是執(zhí)行結果蠕嫁,右側是GraphQL查詢文檔,配合這三個區(qū)域毯盈,我們可以很方便的獲取任意我們想要獲取的數(shù)據(jù)剃毒,下面由淺入深的介紹如何從Github獲取數(shù)據(jù)。首先是最簡單的一個例子搂赋,我想獲取當前登錄的賬號的一些基本信息赘阀,包括賬號名字,郵箱脑奠,id基公,下面是查詢語句:
query {
viewer {
login
url
id
}
}
查詢的結果如下:
{
"data": {
"viewer": {
"login": "pandening",
"url": "https://github.com/pandening",
"id": "MDQ6VXNlcjE2MjI1Nzk2"
}
}
}
如果現(xiàn)在我想要獲取我的簽名呢?只需要在查詢語句中增加一個Field就可以了:
query {
viewer {
login
url
id
bio
}
}
返回的結果如下:
{
"data": {
"viewer": {
"login": "pandening",
"url": "https://github.com/pandening",
"id": "MDQ6VXNlcjE2MjI1Nzk2",
"bio": "/╲/\\╭? oo??oo ?╮/\\╱\\"
}
}
}
從返回的結果可以看出宋欺,我的登錄賬號的名字叫做pandening轰豆,我的主頁url為https://github.com/pandening,id為MDQ6VXNlcjE2MjI1Nzk2齿诞,我的簽名為“/╲/\╭? oo??oo ?╮/\╱\”(非主流八嵝荨),可以發(fā)現(xiàn)返回的json和查詢的輸入是一對一的祷杈,這就是所謂的精準查詢斑司,不多不少,正好合適但汞。那現(xiàn)在來說說如何寫一個查詢呢宿刮?比如我上面的查詢語句是怎么寫出來的呢互站?這就的配合右側的接口文檔了,點開文檔可以看到有兩種類型的操作僵缺,一種是Query云茸,用于查詢數(shù)據(jù),另外一種是Mutation谤饭,用于向服務端發(fā)送寫請求标捺,本文主要關注的是讀數(shù)據(jù),也就是Query操作揉抵,關于Mutation的相關內容也是類似的亡容。點開Query,我們可以看到下面的內容:
上面我使用了viewer來查詢當前登錄的Github的信息冤今,所以點開viewer闺兢,就可以看到我們可以獲取的Field了,如果該Field為標量類型戏罢,那么可以直接返回屋谭,比如id,如果某個Field不是標量的龟糕,比如followers桐磁,它就不是一個標量,那么就要一直查詢直到返回標量為止讲岁。上面的例子很簡單我擂,但是通過這個例子可以開始結合接口文檔來進行復雜的查詢了,下面缓艳,有一個需求校摩,需要獲取當前賬號的名字,url阶淘,簽名衙吩,加入Github的時間,郵箱溪窒,以及該賬號的前5個followers(賬號名坤塞、bio、郵箱霉猛、加入Github的時間)尺锚,當前賬號的前5個倉庫(名字、star信息惜浅、fork信息)瘫辩,下面是構造出來的GraphQL查詢語句:
query {
viewer {
login
url
bio
email
createdAt
followers(first : 5) {
edges {
node {
name
bio
email
createdAt
}
}
}
repositories(first : 5, isFork : false) {
edges {
node {
name
stargazers (first : 10){
edges {
starredAt
node {
name
}
}
}
forks (first : 10){
edges {
node {
createdAt
name
}
}
}
}
}
}
}
}
返回的結果如下:
{
"data": {
"viewer": {
"login": "pandening",
"url": "https://github.com/pandening",
"bio": "/╲/\\╭? oo??oo ?╮/\\╱\\",
"email": "1425124481@qq.com",
"createdAt": "2015-12-09T14:17:52Z",
"followers": {
"edges": [
{
"node": {
"name": "Wang Weitao",
"bio": "",
"email": "softweitao@126.com",
"createdAt": "2012-10-16T16:02:17Z"
}
},
{
"node": {
"name": "Nthan",
"bio": "",
"email": "664157212@qq.com",
"createdAt": "2013-01-16T02:21:07Z"
}
},
{
"node": {
"name": "Mateusz Bagiński",
"bio": "Python/JavaScript Developer",
"email": "cziken58@gmail.com",
"createdAt": "2013-03-23T12:49:03Z"
}
},
{
"node": {
"name": "Dalin Huang",
"bio": "these violent delights have violent ends",
"email": "dhuan023@gmail.com",
"createdAt": "2014-01-26T20:07:36Z"
}
},
{
"node": {
"name": "Ramsey",
"bio": "Arsenal Fan",
"email": "kiminh@sjtu.edu.cn",
"createdAt": "2014-07-18T13:01:22Z"
}
}
]
},
"repositories": {
"edges": [
{
"node": {
"name": "HJSTL",
"stargazers": {
"edges": [
{
"starredAt": "2016-05-08T04:12:01Z",
"node": {
"name": "Jian Hu"
}
}
]
},
"forks": {
"edges": [
{
"node": {
"createdAt": "2017-01-11T02:14:01Z",
"name": "hjstl"
}
}
]
}
}
},
{
"node": {
"name": "AcppLib",
"stargazers": {
"edges": [
{
"starredAt": "2016-08-21T03:33:14Z",
"node": {
"name": "Jian Hu"
}
}
]
},
"forks": {
"edges": []
}
}
},
{
"node": {
"name": "poj-solution",
"stargazers": {
"edges": [
{
"starredAt": "2016-08-22T12:20:41Z",
"node": {
"name": "Jian Hu"
}
}
]
},
"forks": {
"edges": [
{
"node": {
"createdAt": "2016-12-29T21:18:04Z",
"name": "poj-solution"
}
}
]
}
}
},
{
"node": {
"name": "storm-example-onlineusers",
"stargazers": {
"edges": [
{
"starredAt": "2016-08-22T12:24:23Z",
"node": {
"name": "Jian Hu"
}
}
]
},
"forks": {
"edges": []
}
}
},
{
"node": {
"name": "storm-jsoup-spider",
"stargazers": {
"edges": [
{
"starredAt": "2016-08-24T04:40:58Z",
"node": {
"name": "Jian Hu"
}
}
]
},
"forks": {
"edges": []
}
}
}
]
}
}
}
}
看著很復雜,但是只要照著右側的GraphQL接口文檔就可以快速的組裝出我們需要的數(shù)據(jù)了,當然伐厌,你可以組裝任意復雜的查詢語句承绸,只要符合GraphQL的查詢語句的要求,都可以從Github 獲取數(shù)據(jù)挣轨,但是需要注意的一點是军熏,GraphQL確實可以一次性獲取很全面的數(shù)據(jù),但是也需要考慮響應時間的問題卷扮,不能一次性獲取了大量的數(shù)據(jù)荡澎,但是延時很高,這樣的應用的用戶體驗是很差的晤锹,需要權衡一下摩幔。
結語
本文是關于GraphQL系列的第二篇文章,主要介紹了Github的V4 API中的一些新概念鞭铆,以及如何使用V4 API來獲取我們想要的數(shù)據(jù)或衡,文中首先介紹了一個比較簡單的查詢,然后是一個相對復雜的查詢车遂,并且介紹了如何依靠Github提供的GraphQL接口文檔來設計自己的GraphQL查詢語句封断,根據(jù)Github提供的GraphQL文檔,我們可以從Github獲取足夠復雜的數(shù)據(jù)舶担。Github的API設計一直以來都是業(yè)界的標桿坡疼,包括V3的Rest接口,以及V4的GraphQL接口柄沮,都值得仔細學習回梧。