Express、GraphQL以及MongoDB使用和访问数据

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如何操作。

猜你喜欢

转载自blog.csdn.net/weixin_44813858/article/details/132123886