GraphQL
介绍
- GraphQL是Facebook开发的一种数据查询语言,并于2015年公开发布,它是REST API的替代品
- GraphQL既是一种用于API的查询语言也是一个满足数据查询运行时,GraphQL对API中的数据提供了一套易于理解的完整描述,使得客户端能够准确地获得它需要的数据,而且没有任何冗余,更容易随着时间推移而演进
- 官网 - https://graphql.org/
特点
- 请求需要的数据,不少不多
- 获取多个资源,只用一个请求
- 描述所有可能类型的系统,便于维护,根据需求平滑演进,添加或者隐藏字段
GraphQL与restful对比
- restful一个接口只能返回一个资源,graphql一次可以获取多个资源
- restful用不同的url来区分资源,graphql用类型区分资源
GraphQL的基本使用
const express = require('express')
const { buildSchema } = require('graphql')
const {graphqlHTTP} = require('express-graphql')
//定义schema,查询
const schema = buildSchema(`
type Query {
hello:String
}
`)
const root = {
hello:() => {
return 'hello world'
}
}
const app = express()
app.use('/graphql',graphqlHTTP({
schema:schema,
rootValue:root,
graphiql:true
}))
app.listen(3000)
参数类型和参数传递
- 和js传递参数一样,小括号内定义形参,但是注意:参数需要定义类型
- !(叹号)表示参数不能为空
const express = require('express')
const { buildSchema } = require('graphql')
const {graphqlHTTP} = require('express-graphql')
//定义schema,查询和类型
const schema = buildSchema(`
type Account{
name:String
age:Int
sex:String
department:String
salary(city:String):Int
}
type Query {
getClassMates(classNa:Int!):[String]
account(username:String):Account
}
`)
//定义查询对应的处理器
const root = {
getClassMates({classNa}){
const obj = {
31:['111','222','3333'],
61:['4444','5555','6666']
}
return obj[classNa]
},
account({username}){
const name = username
const sex = 'man'
const age = 18
const department = '开发部'
const salary = ({city}) => {
if(city === '111' || city === '222' || city === '3333'){
return 10000
}
return 3000
}
return{
name,sex,age,department,salary
}
}
}
const app = express()
app.use('/graphql',graphqlHTTP ({
schema:schema,
rootValue:root,
graphiql:true
}))
app.listen(3000)
#### clients
hellow-world.js
const express = require('express')
const { buildSchema } = require('graphql')
const {graphqlHTTP} = require('express-graphql')
//定义schema,查询和类型
const schema = buildSchema(`
type Account{
name:String
age:Int
sex:String
department:String
salary(city:String):Int
}
type Query {
getClassMates(classNa:Int!):[String]
account(username:String):Account
}
`)
//定义查询对应的处理器
const root = {
getClassMates({classNa}){
const obj = {
31:['111','222','3333'],
61:['4444','5555','6666']
}
return obj[classNa]
},
account({username}){
const name = username
const sex = 'man'
const age = 18
const department = '开发部'
const salary = ({city}) => {
if(city === '111' || city === '222' || city === '3333'){
return 10000
}
return 3000
}
return{
name,sex,age,department,salary
}
}
}
const app = express()
app.use('/graphql',graphqlHTTP ({
schema:schema,
rootValue:root,
graphiql:true
}))
app.use(express.static('public'))
app.listen(3000)
index.html
<button onclick="getData()">获取数据</button>
<script>
function getData(){
const query = `
query Account($username:String){
account(username:$username){
name
age
sex
salary(city:"111")
}
}
`
const variables = {username:'哈哈哈'}
fetch('/graphql',{
method:"post",
headers:{
'Content-Type':'application/json',
'Accept':'application/json'
},
body:JSON.stringify({
query:query,
variables:variables
})
}),then(json => res.json).then(json => {
console.log(data);
})
}
</script>
使用Mutation修改数据
- 查询用query,修改用Mutation
const express = require('express')
const {buildSchema, isInputObjectType} = 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{
accounts:[Account]
}
`)
const fakeDb = {}
//定义查询对应的处理器
const root = {
accounts(){
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 updateAccount
}
}
const app = express()
app.use('/graphql',graphqlHTTP({
schema:schema,
rootValue:root,
graphiql:true
}))
app.listen(3000)
认证与中间件
//认证
const middlaware = (req,res,next) => {
if(req.url.indexOf('/graphql') !== -1 && req.headers.cookie.indexOf('auth') === -1 ){
res.send(JSON.stringify({
error:"您没有权限访问!"
}))
return
}
next()
}
app.use(middlaware)
Constructing Type
- 使用GraphQLObjectType定义type(类型)
- 使用GraphALObjectType定义query(查询)
查询)
[外链图片转存中…(img-t6bIR0hO-1607994356170)]
与数据库连接
`