GraphQL 實戰(zhàn):Github V4 API使用

作者: 一字馬胡
轉載標志 【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接口柄沮,都值得仔細學習回梧。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末废岂,一起剝皮案震驚了整個濱河市祖搓,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌湖苞,老刑警劉巖拯欧,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異财骨,居然都是意外死亡镐作,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進店門隆箩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來该贾,“玉大人,你說我怎么就攤上這事捌臊⊙畹埃” “怎么了?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長逞力。 經(jīng)常有香客問我曙寡,道長,這世上最難降的妖魔是什么寇荧? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任举庶,我火速辦了婚禮,結果婚禮上揩抡,老公的妹妹穿的比我還像新娘户侥。我一直安慰自己,他們只是感情好峦嗤,可當我...
    茶點故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布添祸。 她就那樣靜靜地躺著,像睡著了一般寻仗。 火紅的嫁衣襯著肌膚如雪刃泌。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天署尤,我揣著相機與錄音耙替,去河邊找鬼。 笑死曹体,一個胖子當著我的面吹牛俗扇,可吹牛的內容都是我干的。 我是一名探鬼主播箕别,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼铜幽,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了串稀?” 一聲冷哼從身側響起除抛,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎母截,沒想到半個月后到忽,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡清寇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年喘漏,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片华烟。...
    茶點故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡翩迈,死狀恐怖,靈堂內的尸體忽然破棺而出盔夜,到底是詐尸還是另有隱情负饲,我是刑警寧澤搅方,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站绽族,受9級特大地震影響姨涡,放射性物質發(fā)生泄漏。R本人自食惡果不足惜吧慢,卻給世界環(huán)境...
    茶點故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一涛漂、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧检诗,春花似錦匈仗、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至攻泼,卻和暖如春火架,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背忙菠。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工何鸡, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人牛欢。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓骡男,卻偏偏與公主長得像,于是被迫代替她去往敵國和親傍睹。 傳聞我的和親對象是個殘疾皇子隔盛,可洞房花燭夜當晚...
    茶點故事閱讀 45,077評論 2 355

推薦閱讀更多精彩內容