Mongoose 中的钩子函数详解及使用示例

阅读时长 7 分钟读完

Mongoose 是一个非常流行的 MongoDB ODM(对象文档映射)工具,它能够帮助我们更方便地在 Node.js 程序中使用 MongoDB 数据库。钩子函数是 Mongoose 中一个非常强大的特性,能够让我们在保存、更新等数据操作前后执行一些代码,实现比较复杂的功能。本文将从钩子函数的基本概念开始,详细介绍 Mongoose 中的钩子函数,并给出一些实际使用场景及示例代码,帮助读者更好地理解和使用这个功能。

什么是钩子函数?

在 Mongoose 中,钩子函数(hook)就是在进行数据库操作(如文档保存、删除、查询等)前后执行的一段程序。例如在保存一个文档前,我们可以执行一些字段校验、默认填充等操作;在查询后,我们可以对查询结果进行一定的处理和过滤。

Mongoose 钩子函数分为两类,分别是 Pre(前置)钩子和 Post(后置)钩子。前置钩子可以在进行数据库操作前执行,后置钩子则可以在操作后执行。钩子函数需要定义在 Schema(模式)中的方法中,Mongoose 会自动调用它们。

如何使用钩子函数?

在 Mongoose 中,钩子函数的使用非常简单。我们可以通过 schema.preschema.post 方法来定义前置和后置钩子函数,以处理存储或读取 MongoDB 数据的各种场景。

Pre Hooks 使用示例

前置钩子可以有多个,执行顺序从前往后。最为常见的一类是 save 钩子函数。当使用 model.save 或实例化后的文档进行 save 操作时都会提前执行。可以在下面示例中看到,在保存文档之前,执行了一些操作,比如校验和默认字段值填充。

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

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

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

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

-- -------------
----- ---- - --- ------------
--------------- -- -
  -- ----- -
    ------------------- ---- --------- -------------
  - ---- -
    ----------------- ----- ----------------
  -
---
展开代码

上述代码执行时,首先我们的 save 钩子函数会被触发,对 name 和 age 进行了校验和默认值填充,之后才会调用 UserModel 的实例 save 方法。

除此之外,Mongoose 还提供了许多其他的钩子函数,包括:

  • validate 一个属性在执行 validate 方法之前触发。通常情况下,可以用于校验特定的字段的输入是否符合要求(如格式、长度等)。

  • remove 该钩子在 Model 实例调用 remove 方法时执行。可以在此进行相关操作,例如同步删除数据前的其他关联数据。

  • update 该钩子在执行 update 方法之前执行。可以尝试做一些条件的更新操作,避免浪费 update 操作。

  • updateOne updateOne 钩子与 update 钩子类似,只是在调用 updateOne 时触发。

更多钩子函数请参见 Mongoose 的官方文档。

Post Hooks 使用示例

和 Pre Hooks 不同,Post Hooks 只能有一个。我们可以通过 schema.post 方法来注册后置钩子函数。下方是一个示例:在 document 上 apply hook,扩展事件追踪的处理,并把结果存到 DB 中。

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

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

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

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

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

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

---------------- -- -
  -- ----- -
    ------------------- ----- --------- -------------
  - ---- -
    ------------------ ----- ----------------
  -
---
展开代码

Async Hooks

从 5.10.0 版本开始,Mongoose 引入了异步钩子函数,可以使用 schema.pre('save', { query: true, document: false }, async function() {}) 的方式来定义。当 query: true 时,该钩子函数会在执行查询前执行(比如 findOne 方式), 当document: true时只有当保存 Mongo 操作的时候执行, 这个特性通常使用在异步场景下(比如异步远程验证、密码哈希),尤其是异步验证更是使用上的方便。如下例所示:

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

  ----- ---- - ----- -------------- ----- --------- ---
  -- ------ -
    ----------------- ------- ----------
    ----- --- ----------- ------- ----------
  -
---
展开代码

异步钩子函数中可以使用 await 等待异步操作的返回结果,可以更方便地处理异步场景下的数据操作。

Conclusion

Mongoose 钩子函数简单易用,但是强大的功能让它非常有用。比如可以在存储、更新数据之前,校验数据、填充默认值、处理关联关系等操作,确保数据的完整性和安全性。钩子函数也能帮助开发者简化代码逻辑,并且可以通过钩子函数更好地实现复杂的业务逻辑。实际项目中可以根据业务需要来选择不同的钩子函数,从而更好地使用 Mongoose 中的特性。

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

纠错
反馈

纠错反馈