nodejs数据持久化--MongoDB(4)mongoose实现restful接口开发

需求
接口地址 http://localhost:3000/api/{model}/{param}
根据不同的model和参数param,实现对不同接口进行增删改查操作

例1:
api = http://localhost:3000/api/user; method = [get, post]
api = http://localhost:3000/api/user/5e16e428f89752a788a555fd; method = [put, delete]

例2:
api = http://localhost:3000/api/article; method = [get, post]
api = http://localhost:3000/api/article/5e16f37d03cf1ea898989bb2; method = [put, delete]

目录结构

restful
│  conf.js
│  index.js
│
├─framework
│    api.js
│    loader.js
│    router.js
│
└─model
     article.js
     user.js

一、数据库参数配置

  • conf.js
module.exports = {
  db: {
    url: 'mongodb://localhost:27017/test_restful',
    options: {
      userNewUrlParser: true
    }
  }
}

二、编写数据模型

  • user.js
module.exports = {
  schema: {
    mobile: {
      type: String,
      required: true
    },
    realName: {
      type: String,
      required: true
    }
  }
}
  • article.js
module.exports = {
  schema: {
    title: {
      type: String,
      required: true
    },
    author: {
      type: String,
      required: true
    }
  }
}

三、编译数据模型model,创建数据库连接

  • loader.js
const fs = require('fs')
const path = require('path')
const mongoose = require('mongoose')
// 加载文件下的model,回调
function load(dir, cb) {
  // 获取绝对路径
  const url = path.resolve(__dirname, dir)
  // 获取model文件,files为数组
  const files = fs.readdirSync(url)
  files.forEach(filename => {
    // 去掉后缀
    filename = filename.replace('.js', '')
    // 导入文件
    const file = require(url + '/' + filename)
    // 回调处理逻辑(文件名,文件)
    cb(filename, file)
  })
}
// 函数柯里化(高价函数)
// 加载编译model
const loadModel = config => app => {
  // 连接数据库
  mongoose.connect(config.db.url, config.db.options)
  const conn = mongoose.connection
  conn.on('error', () => { console.log('数据库连接失败') })
  // 在app上挂载全局model
  app.$model = {}
  // 加载数据表路径下的文件
  load('../model', (filename, { schema }) => {
    // 将schema编译成一个Model
    app.$model[filename] = mongoose.model(filename, schema)
  })
}
module.exports = {
  loadModel
}

四、路由导航

  • router.js
  • init方法拦截实现动态路由
const router = require('koa-router')()
const { init, get, create, update, del } = require('./api')
router.get('/api/:model', init, get)
router.post('/api/:model', init, create)
router.put('/api/:model/:id', init, update)
router.delete('/api/:model/:id', init, del)
module.exports = router.routes()

五、路由拦截,接口实现

  • api.js
module.exports = {
  /**
   * ctx.params.model参数会在model/文件夹下文件名匹配
   * 若文件存在,则取对该文件进行执行接口的操作;否则返回‘no this model’
   * 例;ctx.params.model = 'user'或'article'时;
   * 则当前路由导航的地址就为'http://localhost:3000/api/user' 或 'http://localhost:3000/api/article'
   */
  async init(ctx, next) {
    const model = ctx.app.$model[ctx.params.model]
    if (model) {
      ctx.model = model
      await next()
    } else {
      ctx.body = 'no this model'
    }
  },
  // 查询
  async get(ctx) {
    ctx.body = await ctx.model.find({})
  },
  // 新增
  async create(ctx) {
    const res = await ctx.model.create(ctx.request.body)
    ctx.body = res
  },
  // 修改
  async update(ctx) {
    const res = await ctx.model.updateOne({_id: ctx.params.id}, ctx.request.body)
    ctx.body = res
  },
  // 删除
  async del(ctx) {
    const res = await ctx.model.deleteOne({ _id: ctx.params.id })
    ctx.body = res
  }
}

六、入口文件

  • index.js
const Koa = require('koa')
const app = new Koa()
// 初始化数据库
const config = require('./conf')
const { loadModel } = require('./framework/loader')
loadModel(config)(app)
const restful = require('./framework/router')
const bodyParser = require('koa-bodyparser')
app.use(bodyParser())
app.use(restful)
const port = 3000
app.listen(port, () => {
  console.log(`app start at port ${port}...`)
})

7、执行结果

  • http://localhost:3000/api/user/
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • http://localhost:3000/api/user/
    在这里插入图片描述
    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述
  • http://localhost:3000/api/new
    在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值