EXpress
有了node.js 的基础,可以简单上手express,express是一个简洁而灵活的node.js的web应用框架,其核心特性如下:
- 可以设置多个中间件来响应http请求,处理接口
- 定义了路由表用于执行不同的HTTP请求动作
- 可以通过向模板传递参数来动态渲染HTML页面
- 支持服务端渲染和客户端渲染
需要有node.js的基础,了解中间件、静态资源配置等和核心概念。
GraphQL
GraphQL是一种数据库查询语言,是rest API的替代品。
既是一种用于API的查询语言也是一个满足查询数据的运行时,GraphQL对API的数据提供了一套基于理解的完整描述,使得客户端能够准确获取它需要的数据,而且没有任何冗余,也让API更容易的随着时间的推移而演进。
特点:
- 获取多个资源,只使用一个请求
- 描述所有类似的系统,便于维护,根据需求平滑推进,添加或者隐藏字段
与Restful接口区别:
- restful一个接口只能返回一个资源,而GraphQL可以一次性获取多个资源
- restful用不同的url来区分资源,而FraphQL使用类型来进行区分资源
类型:
- Query : 查询
- Mutation: 操作/修改
MongoDB
MongoD是一个基于分布式文件存储的数据库,介于关系数据库和非关系数据库之间,是非关系型数据库中最像关系型数据库的,支持的数据结构非常松散,是类似于json的bson格式,因此可以存储比较复杂的数据类型,Mongo最大的特点是它支持的查询语言非常强大,其语法类似于面向对象的查询语言,几乎可以实现类似关系数据库表单查询的绝大部分功能,而且支持对数据库建立索引。
特点:
- 高性能
- 易部署
- 易使用
配置MongoDB的方法如下链接,这里不再过多赘述,装完之后建议再装一个可视化工具,否则不易观察数据库状态
使用express利用graphql访问mongodb操作数据
环境(版本一定要匹配):
node -v //v16.20.1
"dependencies": {
"express": "^4.16.4",
"express-graphql": "^0.7.1",
"graphql": "^14.0.2",
"mongoose": "^6.5.0"
}
注意: node的版本一定一定要和graphql版本以及mongoose的版本要适配,否则后续无法进行
node的版本不要太高,我刚开始使用的是18.x版本,后来发现与mongoose不匹配,又开始对node降级到16.20
配置
装好MongoDB之后以管理员身份运行net start MongoDB,启动数据库,打开localhost: 27017如果可以成功访问,说明mongodb服务已经成功启动。
安装好以上版本之后,新建一个js文件:
const express = require('express')
const {
buildSchema} = require('graphql')
const graphqlHttp = require('express-graphql')
// 连接数据库服务
const mongoose = require('mongoose')
mongoose.connect("mongodb://localhost:27017/test")
//设置Schema
const schema = buildSchema(`
type Person{
name: String,
age: Int,
id: String
}
type Query{
getList: [Person],
hello:String
}
input TempInput{
name: String,
age: Int,
}
type Mutation{
createPerson(input: TempInput):Person,
updatePerson(id:String!,input:TempInput):Person,
deletePerson(id: String!): Int
}
`)
//定义模型: 限制数据库films集合的只能存几个字段
var PersonModel = mongoose.model('person',new mongoose.Schema({
name: String,
age: Number
}))
const root = {
createPerson({
input}){
return PersonModel.create({
...input})
},
getList(){
return PersonModel.find()
// return 'getList'
},
hello(){
return 'hello'
},
updatePerson({
id,input}){
return PersonModel.updateOne({
_id: id
},{
...input
}).then(res => PersonModel.find({
_id: id})).then(res =>{
return res[0]
})
},
deletePerson({
id}){
return PersonModel.deleteOne({
_id: id}).then(res => 1)
}
}
const app = express()
app.use('/graphql',graphqlHttp({
rootValue: root,
schema: schema,
graphiql: true // 表示启用graphql调试
}))
//配置静态资源目录
app.use(express.static("public"))
app.listen(3000)// 链接数据库服务,后续前端访问时一定注意跨域问题
const mongoose = require('mongoose')
mongoose.connect("mongodb://localhost:27017/test")
因为上述文件是一个js文件,运行时需要用node运行,但是当代码更改后就会进行失效。可以安装nodemon或者dev-sever运行,在这里我安装的是nodemon,安装命令如下:(注意一定要全局安装)
npm i nodemon -g
启动:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KFR6xmQj-1691236320223)(C:\Users\常静\AppData\Roaming\Typora\typora-user-images\image-20230805134217217.png)]
启动之后就可以去localhost:3000/graphql进行访问和接口的调试了。
我们新建一个临时的html文件,由于express支持静态资源访问,访问: localhost: 3000/html测试接口 利用fetch接口测试一下上述接口:
注意我们使用的是fetch,需要连续两次链式调用才能在第二个链式调用中获取真正的数据
graphql采用的是post接口,如果使用axios或者Xhr调用,一定记得method是post
另: query的模板字符串书写一定严格按照后端的定义来,少一个!都会报错,因此一定注意。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>Home</h1>
<button onclick="getData()">查询数据</button>
<button onclick="createData()">创建数据</button>
<button onclick="updateData()">更新数据</button>
<button onclick="deleteData()">删除数据</button>
<script>
function getData(){
const myQuery = `
query{
getList{
name,
id,
age
}
}
`
fetch("/graphql",{
method:'POST',
headers:{
"Content-Type":"application/json",
"Accept":"application/json"
},
body:JSON.stringify({
query: myQuery
})
}).then(res => res.json()).then(res => {
console.log(res)
})
}
function createData(){
// mutation($input:TempInput) 对标后端的类型
// $input: 表示该值是可变的
const myQuery = `
mutation($input:TempInput){
createPerson(input: $input){
id,
name,
age
}
}
`
fetch("/graphql",{
method:'POST',
headers:{
"Content-Type":"application/json",
"Accept":"application/json"
},
body:JSON.stringify({
query: myQuery,
variables:{
input:{
name:"牡丹",
age: 11,
}
}
})
}).then(res => res.json()).then(res => {
console.log(res)
})
}
function updateData(){
const myQuery = `
mutation($id: String!,$input:TempInput){
updatePerson(id: $id,input: $input){
id,
name,
age
}
}
`
fetch("/graphql",{
method:'POST',
headers:{
"Content-Type":"application/json",
"Accept":"application/json"
},
body:JSON.stringify({
query: myQuery,
variables:{
id:"64cd090d9862f157708ee186",
input:{
name:"百合",
age: 11,
}
}
})
}).then(res => res.json()).then(res => {
console.log(res)
})
}
function deleteData(){
const myQuery = `
mutation($id: String!){
deletePerson(id: $id)
}
`
fetch("/graphql",{
method:'POST',
headers:{
"Content-Type":"application/json",
"Accept":"application/json"
},
body:JSON.stringify({
query: myQuery,
variables:{
id:"64cd090d9862f157708ee186",
}
})
}).then(res => res.json()).then(res => {
console.log(res)
})
}
</script>
</body>
</html>
结果:
查询接口调用完:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lw8egjrJ-1691236320224)(C:\Users\常静\AppData\Roaming\Typora\typora-user-images\image-20230805135847215.png)]
进行修改之后,我们利用studio3可视化工具看一下表里的数据:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NxdTKrbs-1691236320224)(C:\Users\常静\AppData\Roaming\Typora\typora-user-images\image-20230805140101528.png)]
它会自动生成一个string类型的_id,方便标识存储。
下一节记录一下结合react如何操作。