node.js mongoose middleware

目录

官方文档

简介

定义模型

注册中间件

创建doc实例,并进行增删改查

方法名和注册的中间件名相匹配

执行结果

分析

错误处理中间件

手动抛出错误

注意点


官方文档

Mongoose v8.0.3: Middleware

简介

在mongoose中,中间件是一种允许在执行数据库操作前(pre)或后(post)执行自定义逻辑的机制。

定义模型

javascript 复制代码
const mongoose = require('mongoose');
const schema = new mongoose.Schema(
  {
    name: {
      type: String,
      required: true
    }
  },
);

注册中间件

pre为前置中间件,post为后置中间件,允许正则匹配

javascript 复制代码
schema.pre('validate', function(next){  
// this指向正在验证的doc
  console.log('doc validate before')
  next()
})
schema.post('validate', function(doc) { 
//this == doc   true
  console.log('doc validated')
})

schema.pre('save', function(next){  
// this指向正在验证的doc
  console.log('doc save brfore')
  next()
})
schema.post('save', function(doc) {  
//this == doc   true
  console.log('doc saved')
})

schema.pre('init', function(doc) { 
// doc是查询的文档
  console.log('doc init before')
})

schema.post('init', function(doc) {  
// this == doc   true
  console.log('doc inited')
})

schema.pre(/find/, function() {   
//this指向Query实例 
  console.log('doc find')
})

schema.post(/find/, function(doc) { 
// doc是查询的文档
  console.log('doc finded')
})

schema.pre('updateOne', function(next){ 
//this指向Query实例  _conditions: { _id: new ObjectId('658147685eca07e7b0c52259') }
  console.log('doc update before')
  next()
})

schema.post('updateOne', function(res) { 
// res更新结果
  console.log('doc updated') 
})

schema.pre('deleteOne', function(next){  
//this指向Query实例  _conditions: { _id: new ObjectId('658147685eca07e7b0c52259') }
  console.log('doc remove before')
  next()
})

schema.post('deleteOne', function() {  
// res删除结果
  console.log('doc removed')
})

schema.pre('aggregate', function() {  
// this指向正在处理的aggregate
})

schema.pre('aggregate', function() {  
// this指向正在处理的aggregate
})

const Model = mongoose.model('SchemaIdentify', schema)

创建doc实例,并进行 增删改查

javascript 复制代码
app.post('/', async (req, res) => {
  const doc = new Model({
    name: 'saaaaaaaaaa',
  })
  await doc.save()
  await Model.findById(doc._id)
  await Model.updateOne({_id: doc._id}, {name: 'hahahahah'})
  await Model.deleteOne({_id: doc._id})  
  res.status(200).json()
})

方法名和注册的中间件名相匹配

执行结果

分析

Mongoose 内部有一个内置的 pre('save') 钩子,它会调用 validate() 方法,从而触发中间件。因此,在执行 save() 之前,所有注册的 pre('validate') 和 post('validate') 钩子都会被调用

javascript 复制代码
schema.pre('save', async function(next){ // 模拟内置
  await this.validate() // this指向正在处理的doc
  next()
})

注册validate、save、/find/ 、/update/、/delete/等前置中间件接收一个next函数,可以控制next决定是否继续执行注册的中间件, 回调函数中的this有不同的指向,validate、save中间件指向正在处理的文档, /find/ 、/update/、/delete/等中间件中的this指向Query实例。后置中间件validate、save接收一个参数表示处理过的doc,/find/接收一个参数表示查询结果doc或docs、/update/、/delete/等中间件接收一个参数表示处理的结果, 第二个参数为next。

/find/ :

/update/:

/delete/:

错误处理中间件

当执行某操作的时候如果发生错误,后置中间件会接收一个error参数,并且不会继续执行后续的中间件,规定定义三个参数

不传入更新的内容

javascript 复制代码
schema.post('updateOne', function(error, res, next) { // res更新结果
  console.log('doc updated', error)
  next()
})

手动抛出错误

不管是前置、后置,任何中间件中手动抛出一个错误也不会继续往下执行中间件

javascript 复制代码
schema.post(/find/, function(doc) {
  throw new Error('eeeerrror')
})

注意点

1、中间件如果不声明next参数,执行完则默认继续执行下一个中间件,如果中间件声明了next不调用则卡在这个中间件(声明必调用,要不就不声明)

2、在const Model = mongoose.model('SchemaIdentify', schema) 编译之前声明中间件,否则中间件不会执行

3、/update/ 中间件并不会触发save中间件,也就不会调用validate(),即也不会执行validate中间件。可以调用Model.findOneAndUpdate或findByIdAndUpdat,设置第三个参数options { runValidators: true },允许monggose进行数据校验。

相关推荐
Maiko Star5 小时前
FastAPI 进阶三部曲:中间件、依赖注入与 ORM 实战
python·中间件·fastapi
吴声子夜歌6 小时前
MongoDB 4.2——索引(二)
数据库·mongodb·索引
吴声子夜歌20 小时前
MongoDB 4.x——并发优化
数据库·mongodb
吴声子夜歌1 天前
MongoDB 4.2——入门指南
数据库·mongodb
吴声子夜歌1 天前
MongoDB 4.x——高可靠
数据库·mongodb
码农学院1 天前
Node.js MongoDB构建户外用品GEO优化内容管理平台
数据库·mongodb·node.js
吴声子夜歌1 天前
MongoDB 4.x——治理经验
数据库·mongodb
憧憬成为java架构高手的小白2 天前
黑马八股--中间件学习之MQ(RabbitMQ)
学习·中间件
吴声子夜歌2 天前
MongoDB 4.x——应用设计调优
数据库·mongodb
吴声子夜歌2 天前
MongoDB 4.x——高级特性(Change Stream和事务)
数据库·mongodb