Mongoose 是 Node.js 上使用最多的 MongoDB 连接库之一,它提供了一些强大的特性来简化 MongoDB 数据库的使用。其中,pre 和 post 钩子是 Mongoose 中非常重要的特性之一,可以帮助我们在数据库操作前后做一系列自定义的操作,例如数据校验、数据处理等等。本篇文章将详细介绍 Mongoose 中的 pre 和 post 钩子及其使用方法,并给出实用的示例代码。
钩子概览
Mongoose 中的钩子可以在模式上定义,它们允许您执行一些操作,例如:
- 预处理(例如数据校验或规范化)
- 后处理(例如日志记录或数据转换)
先看下如何在模式(Schema)上定义一个钩子:
-- -------------------- ---- ------- ----- ------ - --- ----------------- ----- ------- ---- ------ --- ------------------ ---------- - -- ---- ---- --- ------------------- ---------- - -- ---- ---- ---
如上所示,我们可以在 schema 实例上使用 .pre
和 .post
方法来定义钩子,.pre
和 .post
的第一个参数都是触发的钩子函数,其中.pre
是在执行操作前触发,.post
是在执行操作后触发。
Mongoose 钩子支持的事件有:
init
:当执行mongoose.connect
时触发一次validate
:保存之前数据验证save
:在保存文档前触发remove
:在删除文档前触发deleteOne
:在删除单个文档前触发deleteMany
:在删除多个文档前触发update
:在更新文档前触发findOneAndUpdate
:在查找并更新文档前触发findOneAndRemove
:在查找并删除文档前触发countDocuments
:在统计文档数量前触发
以上事件包括了绝大部分 Mongoose 操作场景,我们可以通过监听这些事件来达到我们要的效果。
pre 钩子
这里我们将主要讲解 pre
钩子,也就是在执行数据库操作前的钩子,它可以帮助我们做一些非常有用的操作,例如请求参数校验,数据预处理等。下面就是一些使用 pre
钩子的示例代码。
1. 请求参数校验
schema.pre('save', function(next) { if (!this.name) { next(new Error('name is required!')); } else { next(); } });
如上所示,我们可以在 save
事件前进行参数校验,如果验证失败,就通过 next
方法传递一个错误信息,否则就调用 next
方法让程序继续执行。
2. 数据预处理
schema.pre('save', function(next) { this.age = parseInt(this.age); next(); });
如上所示,我们可以在 save
事件前进行数据预处理,例如将请求参数中的字符串 age
转化为数字类型。
3. 数据自增
-- -------------------- ---- ------- ----- -------------- - --- ----------------- ----- - ----- ------- --------- ---- -- ---- - ----- ------- -------- - - --- ----- ------- - ------------------------- ---------------- ------------------ -------------- - --- --- - ----- -------------------------- - ----- --------- -- - ----- - ---- - - -- - ---- ----- ------- ---- - ------------------------ - ------ - ------------ ------- ---------------------- - ---------- --- ---
如上所示,我们可以通过 Mongoose 的 findByIdAndUpdate
方法实现自增的功能,将 Counter
集合的 seq
属性值自增1,并返回最新的 seq
属性值。将这个 seq
值赋值给本条数据的 id
属性,再执行 next
方法,程序继续执行后续操作。
4. 加密密码
-- -------------------- ---- ------- ----- ------ - ------------------ ------------------ -------------- - ----- ---- - ----- -- ------------------------------ - ------ ------- - ------------------ ------------- ----- - -- ----- - ------ ---------- - -------------------------- ----- ------------- ----- - -- ----- - ------ ---------- - ------------- - ----- ------- --- --- ---
如上所示,我们在保存用户信息前,通过使用 bcrypt
库对用户的密码进行加密,在校验密码的时候再进行解密匹配,可以保障用户密码的安全性。
post 钩子
除了 pre
钩子,Mongoose 还提供了 post
钩子,它将在操作执行后触发。post
钩子可以用于各种操作,例如数据格式化、数据日志记录等等。下面就是一些使用 post
钩子的示例代码。
1. 返回数据格式化
schema.post('find', function(docs) { return docs.map(function(doc) { doc.userID = ObjectId(doc.userID.toString()); return doc; }); });
如上所示,我们可以在 find
操作后,对数据库查询结果进行格式化,比如将数据库中的 userID
字段值转化为 ObjectId
类型。
2. 日志记录
-- -------------------- ---- ------- ----- --------- - --- ----------------- ----- - ----- ---- -- ---------- - ----- ------ -- -------- - ----- ------ -- --- ----- --- - --------------------- ----------- ------------------- ------------- - ----- --- - --- ----- ----- --- ------- ---------- --------- -------- -- --- -------- --- ---- ----- ---- -- ----------- --- ----------- --- --------------------- ------------- - ----- --- - --- ----- ----- --- ------- ---------- --------- -------- -- -------- ---- -- --------- --- ---- --------- --- ----------- ---
如上所示,我们可以在数据库 save
和 remove
操作后,向日志中记录数据操作信息。
总结
通过本文的介绍,我们了解了 Mongoose 中的 pre
和 post
钩子的基本概念及使用方法。通过使用钩子,我们可以在进行数据库操作前后进行数据预处理、数据格式化、数据校验等操作,增强了程序的健壮性。同时,在实际的开发中,也可以通过自己的创意使用钩子,达到更加优秀的业务目的。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/644fbdaf980a9b385b910618