GraphQL
一、介紹
官網了解一下
這個比較詳細
- GraphQL是Facebook開發的一種資料查詢語言,并于2015年公開釋出,它是REST API的替代品,是用于前後端資料查詢方式的規範
特點:
-
請求需要的資料,不多不少
例如:account中有name,age,sex,department等,可以隻取得需要的字段。
- 擷取多個資源,隻用一個請求.
- 描述所有可能類型的系統。便于維護,根據需求平滑演進,添加或者隐藏字段。
- 可以使用任何資料庫
GraphQL與restful的差別
restful本質就是用定義uri,通過api接口來取得資源
二、參數類型
基本參數類型
- 基本類型:String/Int/Float/Boolean/ID,可以在schema聲明的時候直接使用。
- [類型]代表數組,例如:[Int]代表整型數組。
schema定義結構
[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-Ilhgjj0v-1628752516184)(/Users/shulun-001/Library/Application Support/typora-user-images/image-20210805155214977.png)]
自定義參數類型
#GraphQL允許使用者自定義參數類型,通常用來描述要擷取的資源的屬性。
#一般寫在schema.graphl裡頭定義類型
type Account{
name:String
age:Int
sex:String
salary(city:String):Int
}
type Query{
account(name:String):Account //定義一個Account屬性,然後在Account類型中進行傳回
}
參數傳遞
- 和js傳遞參數一樣,小括号内定義形參,但是注意:參數需要定義類型。
- !(歎号)代表參數不能為空
三、GraphQL clients
GraphQL 有一種一流的方法可以從查詢中提取動态值,并将它們作為單獨的字典傳遞。這些值稱為變量。
1. 查詢資料用query
[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-KT836bNs-1628752516186)(/Users/shulun-001/Library/Application Support/typora-user-images/image-20210804114157114.png)]
第一行大寫(類型和之前定義的一樣),第二行小寫,傳入$user.id
GraphQL查詢規範:
1.片段(fragments)
請求就用nuxt異步請求
2.mutations修改資料
[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-jPmYPmIB-1628752516187)(/Users/shulun-001/Library/Containers/com.tencent.xinWeChat/Data/Library/Caches/com.tencent.xinWeChat/2.0b4.0.9/33cd611f706d6acfa48413cd90846f4d/dragImgTmp/WeChatef176becb29f23d693b7043534d856e1.png)]
例子:
const express = require('express');
const {buildSchema}=require('graphql');
const graphqlHTTP=require('express-graphql');
//定義schema,查詢和類型,mutation
const schema=buildSchema(`
input AccountInput{
name:String
age:Int
sex:String
department:String
}
type Account{
name:String
age:Int
sex:String
department:String
}
type Mutation{
createAccount(input:AccountInput):Account
updateAccount(id:ID!,input:AccountInput):Account
}
type Query{
account:[Account]
}
`)
const fakeDB={};
//定義查詢對應的處理器
const root={
account(){
var arr=[];
for(const key in fakeDB){
arr.push(fakeDB[key])
}
return arr;
},
createAccount({input}){
//相當于資料庫的儲存
fakeDB[input.name]=input;
//傳回儲存結果
return fakeDB[input.name];
},
updateAccount({id,input}){
//相當于資料庫的更新
const updateAccount=Object.assign({},fakeDB[id],input);
fakeDB[id]=updateAccount;
//傳回資料庫
return updatedAccount;
}
}
const app=express();
app.use('/graphql',graphqlHTTP({
schema:schema,
//相當于項目中運作yarn schema
rootValue:root,
graphiql:true
}))
app.listen(3000)
3.結合資料庫寫的一個例子
const express = require('express');
const {
buildSchema
} = require('graphql');
const graphqlHTTP = require('express-graphql');
const mysql = require('mysql');
// https://www.npmjs.com/package/mysql
var pool = mysql.createPool({
connectionLimit: 10,
host: 'localhost',
user: 'root',
password: 'root',
database: 'xxxx'
})
//定義schema,查詢和類型,mutation
const schema = buildSchema(`
input AccountInput{
name:String
age:Int
sex:String
department:String
}
type Account{
name:String
age:Int
sex:String
department:String
}
type Mutation{
createAccount(input:AccountInput):Account
deleteAccount(id:ID):Boolean
updateAccount(id:ID!,input:AccountInput):Account
}
type Query{
account:[Account]
}
`)
const fakeDB = {};
//定義查詢對應的處理器
const root = {
account() {
return new Promise((resolve,reject)=>{
pool.query('select name,age,sex,department from account',(err,results)=>{
if(err){
console.log('error',err.message);
return;
}
const arr=[];
for(const i=0;i<results.length;i++){
arr.push({
name:results[i].name,
sex:results[i].sex,
age:results[i].age,
department:results[i].department,
})
}
resolve(results);
})
})
},
createAccount({
input
}) {
const data = {
name: input.name,
sex: input.sex,
age: input.age,
department: input.department
}
return new Promise((resolve, reject) => {
pool.query('insert into accout set ?', data, (err) => {
if (err) {
console.log('error',err.message);
return;
}
//傳回儲存結果
resolve(data);
})
})
},
updateAccount({
id,input
}) {
const data=input;
return new Promise((resolve,reject)=>{
pool.query('update account set?where name=?',[data,id],(err)=>{
if(err){
console.log('err',err.message);
return;
}
resolve(data);
})
})
},
deleteAccount({id}){
return new Promise((resolve,reject)=>{
pool.query('delete account where name=?',[id],(err)=>{
if(err){
console.log("err",err.message)
reject(false);
return;
}
resolve(true);
})
})
}
}
const app = express();
//增加一個判斷權限的中間件
const middleware = (req, res, next) => {
if (req.url.indexOf('/graphql') != -1 && req.headers.cookie.indexOf('auth')) {
res.send(JSON.stringify({
error: "您沒有權限通路這個接口"
}));
return;
}
next();
}
//使用中間件
app.use(middleware)
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true
}))
app.listen(3000)
4.了解schema
Schema的主要用途是定義所有可供查詢的字段(field),它們最終組合成一套完整的GraphQL
API.