koa2+mongoose 操作数据日志

1 篇文章 0 订阅
1 篇文章 0 订阅

最近公司让做操作日志记录(koa2+mongoose),听到这个消息我撸起袖子就开始干了,但有几个地方还需要注意下:

  1. 功能部分已经做完了,不能修改别人的代码(小部分还是可以的)
  2. 每个请求的操作可能会操作多张不同的表
  3. 需要记录每个请求操作数据(操作前和操作后的数据,可用于恢复数据)

要追踪到每次操作数据库的操作,肯定不能再每次具体操作方法的地方都去把操作前数据和操作后的数据保存起来,这样工作量很大,其他功能的每个地方基本上都会被动一次,那么怎么样才能做到追踪到每次操作而不用具体到每个操作方法呢?

中间件+mongoose的hook函数

中间件是个很好的东西,什么是中间件这里不做说明,不明白的可以自行百度,这里贴下中间件的代码:

module.exports = async (ctx, next) => {
  try {
      // get请求跳过不记录操作日志
    if (ctx.method === 'GET') {
      await next()
    } else {
      // 建立全局对象用于中间价与mongoose传递参数
      if (!global.userLogs) global.userLogs = {}
      // 区分每次请求用到了 请求方法+url 作为key (我们用的restfull风格)
      const _logctx = ctx.method + '_' + ctx.url
      // 在全局变量中 添加该属性
      global.userLogs[_logctx] = {
        url: ctx.url,
        method: ctx.method,
        ip: ctx.ip,
        beforeData: '',
        afterData: '',
        time: Math.floor(new Date().getTime() / 1000)
      }
      await next()
      // 打印需要处理的数据(这里是保存等操作)
      console.log(global.userLogs[_logctx])
    }
  } catch (error) {
    console.log(error)
  }
}

mongoose 是个orm 框架,与我们应用的逻辑程序没有直接关系,所以我这里用到了全局变量用来传递参数,后面再做具体的每种操作时会给global.userLogs赋值。

由于公司之前用mongoose 建立的model都是每个各自建立自己的model,所有在再做统一处理是就很麻烦了,需要自每个model都要修改,为了避免上的麻烦我建立一个base.model.js 一些公共的东西都放在这里,让所有的model都去引用这个model,代码如下:

const mongoose = require('mongoose')
const Schema = mongoose.Schema

const schema = new Schema()

// 监听方法名称
const methods = [
  // 'init',
  // 'validate',
  // 'count',
  // 'find',
  // 'findOne',
  'save',
  'remove',
  'findOneAndRemove',
  'findOneAndUpdate',
  'insertMany',
  'update'
]

methods.forEach(n => {
  // 操作前处理方法
  schema.pre(n, function(next) {
    if (n === 'save') {
      global.userLogs[this._logctx].afterData += JSON.stringify(delete this._logctx)
    } else {
      const _logctx = this.options._logctx
      global.userLogs[_logctx].afterData += this._update ? JSON.stringify(this._update) : ''
    }
    next()
  })

  // 操作后处理方法
  schema.post(n, function(data) {
    if (n !== 'save') {
      const _logctx = this.options._logctx
      global.userLogs[_logctx].beforeData += JSON.stringify(data)
    }
  })
})

// 保存方法特殊处理(保存方法option 数据传递不过来)
schema.method({
  'create': (data, model, ctx) => {
    data._logctx = {logctx: ctx.method + '_' + ctx.url}
    this.mongoose.models[model].create(data)
  }
})

exports.schema = schema
exports.mongoose = mongoose

methods 对象里面放的是所有mongoose所有hook函数(pre(操作前), post(操作后))能监听到的方法名称,里面注释掉的部分不属于我们操作记录范围内(增、删、改),有人可能回问这里的方法不全,比如,保存数据除了save()还有create()方法,其实create的方法内部还是走的是save(),所以监听save,同时可以监听create和save方法。

上面我们说过,mongoose是个独立orm框架,只处理数据库相关操作,不会牵扯逻辑相关数据,那我们怎样才能让mongoose知道这次操作,是哪个请求方法在操作呢?

mongoose在每次操作数据数据是会有个配置项(options), 这个配置项会被传递到具体操作方法(蛋疼的save方法除外),这样我们就可以在操作数据的时候拿到请求相关信息了,把请求数据放在global.userLogs对象里key 这里_logctx需要和前面中间件中命名一致(请求类型+url),在这里修改前面中间中定义相应的属性值。

mongoose中save方法比较特殊,因为没有配置项(option)或参数传递不过来,在pre和post函数中,参数只有保存的对象,取不到别的参数,由于我们公司全部使用的是create方法保存对象,所以我只需要重写create方法,在create方法中添加了_logctx 属性,属相值为我配拼写的(请求类型+url),然后调用原始的create方法,需要注意的是在重写方法中this是取不到当前model的,这里取到的是所有的model,需要把当前model 传递过来,所以我吧model 名称也传过来,方便获取当前model(这个方法比较笨,肯定还有更好的方法,有的话请留言指出),由于mongoose 的特性,在model 中没有定义相应的字段,所以在保存时_logctx 字段是保存不进去的。

最后在上面中间件的 await next() 后面根据key 值得不同取到相应的数据,执行存储或者其他操作。


我写完上面的方法之后,领导告诉我,只要处理逻辑层面就行(只记录请求接口和请求结果就行了),不用这么复杂,╮(╯▽╰)╭……

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Koa2是一个基于Node.js的Web开发框架,而MySQL是一种关系型数据库管理系统。将它们结合起来,可以更方便地进行Web开发。 以下是Koa2和MySQL入门的基本步骤: 1. 安装Koa2和MySQL模块 使用npm安装koa和mysql模块: ``` npm install koa mysql ``` 2. 连接MySQL数据库 在应用程序中,需要连接到MySQL数据库。可以使用以下代码: ``` const mysql = require('mysql'); const connection = mysql.createConnection({ host: 'localhost', user: 'root', password: 'password', database: 'database_name' }); connection.connect(); ``` 其中,`host`是数据库服务器的地址,`user`是用户名,`password`是密码,`database`是要连接的数据库名称。 3. 执行SQL查询 连接到数据库后,可以执行SQL查询。以下是一个简单的查询示例: ``` connection.query('SELECT * FROM users', function (error, results, fields) { if (error) throw error; console.log(results); }); ``` 在这个示例中,使用`SELECT`语句从`users`表中检索所有行。查询结果将在控制台中打印出来。 4. 在Koa2中使用MySQL 在Koa2应用程序中,可以使用`koa-mysql`模块来更方便地使用MySQL。以下是一个简单的示例: ``` const Koa = require('koa'); const app = new Koa(); const mysql = require('koa-mysql'); app.use(async (ctx, next) => { const db = await mysql.createPool({ host: 'localhost', user: 'root', password: 'password', database: 'database_name' }); const results = await db.query('SELECT * FROM users'); ctx.body = results; }); app.listen(3000); ``` 在这个示例中,使用`koa-mysql`模块创建一个MySQL连接池。然后,使用`query`方法从`users`表中检索所有行,并将结果作为响应主体发送给客户端。 这只是一个简单的入门示例。在实际应用中,可能需要更复杂的查询和数据操作。但是,通过这个入门示例,您应该已经了解了如何将Koa2和MySQL结合起来进行Web开发。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值