GraphQL簡明教程(graphql 教程)
GraphSQL是為了解決REST API存在的問題而提出的一種新的查詢語言。GraphQL將數(shù)據(jù)對象關(guān)系映射到一個圖(Graph),并設(shè)計了一種查詢語言(Query Language)來遍歷圖中關(guān)系 —— 這也是GraphQL名稱的來源。本教程將介紹GraphQL規(guī)范的基本內(nèi)容并使用nodejs實現(xiàn)一個簡單但完整的GraphQL API服務(wù)。
類似于我們熟悉的SQL(Strutural Query Language),GraphSQL也只是規(guī)范,你可以使用任何語言來實現(xiàn)GraphQL規(guī)范。目前已經(jīng)有了采用各種主流編程語言的實現(xiàn),不過在本文中,我們將使用官方提供的JavaScript版本的GraphQL參考實現(xiàn)代碼。
如果希望快速掌握區(qū)塊鏈應用的開發(fā),推薦匯智網(wǎng)的區(qū)塊鏈應用開發(fā)系列教程, 內(nèi)容涵蓋比特幣、以太坊、eos、超級賬本fabric和tendermint等多種區(qū)塊鏈,以及 java、go、nodejs、python、php、c#、dart等多種開發(fā)語言。
1、GraphQL的基礎(chǔ)架構(gòu)
同樣類似于SQL,在GraphQL規(guī)范中約定了兩個組件:服務(wù)器和客戶端。
服務(wù)器負責處理查詢請求,解析查詢并使用指定的格式提取數(shù)據(jù),然后通常以JSON 格式返回響應。
應用程序可以使用客戶端實現(xiàn)與GraphQL的通信,雖然也可以直接向GraphQL服務(wù)器 的訪問端結(jié)點發(fā)送一個HTTP POST請求,但是GraphQL客戶端提供了更多的功能。
構(gòu)建一個Graph API會比構(gòu)建一個REST API的工作量大,但是在速度和可用性方面的提升可以彌補它的復雜性。
2、初識GraphQL
現(xiàn)在我們的小目標是發(fā)送一個GraphQL查詢請求,然后獲取一個響應,以此來初步了解GraphQL。
記住,GraphQL是一種自創(chuàng)一派的查詢語言,它不難學,而且大多數(shù)情況下查詢的寫法很合直覺,容易理解。
現(xiàn)在先讓我們假設(shè)有一個航班和乘客信息數(shù)據(jù)庫。
在GraphQL中,我們可能這樣來查詢一個航班:
{
flight(id: “1234”) {
origin
destination
}
}
這個GraphQL查詢語句的意思是:查詢航班(flight)1234的出發(fā)地(origin)和目的地(destination)。
上述查詢的響應如下:
{
“data”: {
“flight”: {
“origin”: “DFW”,
“destination”: “MKE”
}
}
}
你看,雖然航班信息可能包含很多字段,但是由于我們在查詢語句中指定了要返回的字段,所以服務(wù)器精準的只返回這一部分數(shù)據(jù),不多也不少。
這有點像你在SQL查詢時指定返回字段的感覺,不過GraphQL比這個還要強。假設(shè)接下來要查詢航班1234的出發(fā)地、目的地以及所有乘客的姓名,可以這樣寫查詢語句:
{
flight(id: “1234”) {
origin
destination
passengers {
name
}
}
}
在這個查詢中,GraphQL就需要考慮航班數(shù)據(jù)、乘客數(shù)據(jù)以及這兩者的關(guān)系了。
響應結(jié)果如下:
{
“data”: {
“flight”: {
“origin”: “DFW”,
“destination”: “MKE”,
“passengers”: [
{
“name”: “Luke Skywalker”
},
{
“name”: “Han Solo”
},
{
“name”: “R2-D2”
}
]
}
}
}
COOOOOOOOOOOOOOOOOOOOOOOL!我們只進行了一次API調(diào)用就同時獲取了航班的起止地點以及全部乘客的名字!
由于GraphQL將數(shù)據(jù)關(guān)系視為圖,因此我們可以從任意方向進行遍歷,例如查詢乘客Luke Skywalker的護照號以及所乘航班的編號、日期、出發(fā)地和目的地:
{
person(name: “Luke Skywalker”) {
passport_number
flights {
id
date
origin
destination
}
}
這個查詢的返回結(jié)果看起來是這樣:
{
“data”: {
“person”: {
“passport_number”: 78120935,
“flights”: [
{
“id”: “1234”,
“date”: “2019-05-24”,
“origin”: “DFW”,
“destination”: “MKE”
},
{
“id”: “2621”,
“date”: “2019-07-05”,
“origin”: “MKE”,
“destination”: “DFW”
}
]
}
}
}
3、實現(xiàn)GraphQL API
前面我們了解了GraphQL的查詢與響應交互?,F(xiàn)在我們了解如何實現(xiàn)GraphQL Server。下面列出了接下來要做的工作:
選擇一個實現(xiàn)GraphQL Server的開發(fā)框架,我們選擇express
定義數(shù)據(jù)架構(gòu),以免GraphQL知道如何路由收到的查詢請求
創(chuàng)建用于處理請求并返回響應結(jié)果的解析函數(shù)
構(gòu)建訪問端結(jié)點
編寫客戶端查詢進行測試
然后,你就可以在客戶端應用中使用GraphQL的強大查詢能力了,不過在本教程中我們不會涉及如何在你的應用中嵌入GraphQL查詢能力。另外,在現(xiàn)實應用中,絕大多數(shù)GraphQL的應用都會涉及到數(shù)據(jù)庫,不過在這個教程中我們也不會涉及數(shù)據(jù)庫的操作。
3.1 實現(xiàn)GraphQL服務(wù)器
首先,確保你已經(jīng)安裝了nodejs和npm。
接下來讓我們創(chuàng)建一個Express服務(wù)器。先初始化:
$ npm initThis utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.See `npm help json` for definitive documentation on these fields
and exactly what they do.Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.Press ^C at any time to quit.
package name: (graphql-medium)
version: (1.0.0)
description:
entry point: (index.js)
test command:
git repository:
keywords:
author:
license: (ISC)
About to write to /home/bennett/Repos/graphql-medium/package.json:{
“name”: “graphql-medium”,
“version”: “1.0.0”,
“description”: “”,
“main”: “index.js”,
“scripts”: {
“test”: “echo “Error: no test specified” && exit 1″
},
“author”: “”,
“license”: “ISC”
}Is this OK? (yes)
你可以一路回車下來,以后還有機會修改生成的package.json。
接下來,讓我們安裝Express、GraphQL和Express-GraphQL庫:
$ npm install express express-graphql graphqlnpm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN graphql-medium@1.0.0 No description
npm WARN graphql-medium@1.0.0 No repository field. express-graphql@0.8.0
graphql@14.3.1
express@4.17.0
added 53 packages from 38 contributors and audited 151 packages in 6.169s
found 0 vulnerabilities
現(xiàn)在,創(chuàng)建文件index.js,實現(xiàn)一個基本的Express Server:
// index.js
const express = require(‘express’);
const app = express();
app.get(‘/’, function(req, res) {
res.send(‘Express is working!’)
});
app.listen(4000, function() {
console.log(‘Listening on port 4000’)
});
試著運行命令node index.js,你應當會看到如下提示信息:
Listening on port 4000
使用瀏覽器訪問http://localhost:4000/,就可以看到如下內(nèi)容:
Express is working!”
3.2 定義數(shù)據(jù)架構(gòu)
首先,我們引入必要的模塊:
const graphqlHTTP = require(‘express-graphql’);
const { buildSchema } = require(‘graphql’);
接下來讓我們先定義一個hello world數(shù)據(jù)架構(gòu)來讓代碼跑起來。
let schema = buildSchema(`
type Query {
hello: String
}
`);
這個簡單的數(shù)據(jù)架構(gòu)的作用,就是告訴GraphQL當有查詢hello時,我們要返回一個字符串。
3.3 解析查詢語句
當有人提交對hello的查詢時,我們將要返回一個字符串,這是我們在上面的數(shù)據(jù)架構(gòu)中定義的。
現(xiàn)在我們需要告訴GraphQL應當返回哪個字符串 —— 這就是解析器的作用 ——找出要返回的數(shù)據(jù)。
在這個示例中,解析器非常簡單,我們直接返回一個字符串常量:
return ‘Hello world!’;
1
但是我們需要把上述語言封裝到一個函數(shù)中,任何時候有人查詢hello,只需要調(diào)用這個函數(shù)就可以了:
function() {
return ‘Hello world!’;
}
目前而言,hello是我們實現(xiàn)的唯一的查詢類型。在將來我們也可以包含其他的訪問端結(jié)點。現(xiàn)在先將hello和我們的解析器函數(shù)關(guān)聯(lián)起來:
let root = {
hello: function() {
return ‘Hello world!’;
},
}
3.4 設(shè)置訪問端結(jié)點
你可能會注意到,我們在前面導入了graphqlHTTP,但并沒有使用它?,F(xiàn)在是時候了,我們將創(chuàng)建一個新的路由來提供GraphQL API服務(wù):
app.use(‘/graphql’, graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true,
}));
schema和root都指向我們前面定義的變量。graphiql是一個有用的可視化工具,它與GraphSQL一起安裝,
我們接下來將用它進行GraphQL API的測試。
3.5 查詢測試
現(xiàn)在可以啟動GraphQL服務(wù)器,進行測試了!
啟動應用:node index.js
用瀏覽器訪問http://localhost:4000/graphql
應該看到graphiql的界面:
現(xiàn)在就可以用這個界面來測試我們的GraphQL API了!
{
hello
}
點擊提交按鈕,將會看到:
{
“data”: {
“hello”: “Hello world!”
}
}
IT’S WORKING!!!
原文鏈接:從SQL到GraphQL – 匯智網(wǎng)