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.