Mongoose 中的 pre 和 post 钩子详解

阅读时长 7 分钟读完

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. 请求参数校验

如上所示,我们可以在 save 事件前进行参数校验,如果验证失败,就通过 next 方法传递一个错误信息,否则就调用 next 方法让程序继续执行。

2. 数据预处理

如上所示,我们可以在 save 事件前进行数据预处理,例如将请求参数中的字符串 age 转化为数字类型。

3. 数据自增

-- -------------------- ---- -------
----- -------------- - --- -----------------
  ----- - ----- ------- --------- ---- --
  ---- - ----- ------- -------- - -
---

----- ------- - ------------------------- ----------------

------------------ -------------- -
  --- --- - -----
  --------------------------
    - ----- --------- --
    - ----- - ---- - - --
    - ---- ----- ------- ---- -
  ------------------------ -
    ------ - ------------
    -------
  ---------------------- -
    ----------
  ---
---

如上所示,我们可以通过 Mongoose 的 findByIdAndUpdate 方法实现自增的功能,将 Counter 集合的 seq 属性值自增1,并返回最新的 seq 属性值。将这个 seq 值赋值给本条数据的 id 属性,再执行 next 方法,程序继续执行后续操作。

4. 加密密码

-- -------------------- ---- -------
----- ------ - ------------------

------------------ -------------- -
  ----- ---- - -----
  -- ------------------------------ -
    ------ -------
  -
  ------------------ ------------- ----- -
    -- ----- -
      ------ ----------
    -
    -------------------------- ----- ------------- ----- -
      -- ----- -
        ------ ----------
      -
      ------------- - -----
      -------
    ---
  ---
---

如上所示,我们在保存用户信息前,通过使用 bcrypt 库对用户的密码进行加密,在校验密码的时候再进行解密匹配,可以保障用户密码的安全性。

post 钩子

除了 pre 钩子,Mongoose 还提供了 post 钩子,它将在操作执行后触发。post 钩子可以用于各种操作,例如数据格式化、数据日志记录等等。下面就是一些使用 post 钩子的示例代码。

1. 返回数据格式化

如上所示,我们可以在 find 操作后,对数据库查询结果进行格式化,比如将数据库中的 userID 字段值转化为 ObjectId 类型。

2. 日志记录

-- -------------------- ---- -------
----- --------- - --- -----------------
  ----- - ----- ---- --
  ---------- - ----- ------ --
  -------- - ----- ------ --
---

----- --- - --------------------- -----------

------------------- ------------- -
  ----- --- - --- -----
    ----- --- -------
    ---------- ---------
    -------- -- --- -------- --- ---- ----- ---- -- -----------
  ---
  -----------
---

--------------------- ------------- -
  ----- --- - --- -----
    ----- --- -------
    ---------- ---------
    -------- -- -------- ---- -- --------- --- ---- ---------
  ---
  -----------
---

如上所示,我们可以在数据库 saveremove 操作后,向日志中记录数据操作信息。

总结

通过本文的介绍,我们了解了 Mongoose 中的 prepost 钩子的基本概念及使用方法。通过使用钩子,我们可以在进行数据库操作前后进行数据预处理、数据格式化、数据校验等操作,增强了程序的健壮性。同时,在实际的开发中,也可以通过自己的创意使用钩子,达到更加优秀的业务目的。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/644fbdaf980a9b385b910618

纠错
反馈