Mongoose 中文文档虚拟属性详解

阅读时长 7 分钟读完

在 MongoDB 的 Node.js 驱动 Mongoose 中,虚拟属性是一种模式属性,在对文档进行查询或者保存时会自动进行计算或者转换,但它不会在 MongoDB 中存储。这种特性在很多场景下非常有用,它可以给抽象属性和逻辑增加一个新的维度。

基本概念

在 Mongoose 中,虚拟属性的定义非常简单,我们可以通过在 Schema 中调用 virtual() 方法来声明一个虚拟属性。下面是一个示例:

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

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

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

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

可以看出,虚拟属性并不存储在 MongoDB 中,而是在运行时(取值时)计算得到。虚拟属性有两种类型:gettersetter,它们分别对应着一个属性值的读取和设置。

虚拟属性类型

Getter

Getter 是一个没有 setter 的虚拟属性类型。当我们在代码中访问该属性时,Mongoose 会执行 get 函数来获取该值。我们可以使用 get 函数返回计算过的值,也可以利用它进行一些复杂的运算、逻辑判断等处理。

下面的例子展示如何计算一个用户文档的年龄:

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

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

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

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

Getter 虚拟属性有一个非常重要的特性,它们可以通过虚拟属性计算,这对于需要频繁执行复杂计算的情况非常有用。而且 Getter 属性的计算可以依赖其他属性,方便我们进行维护和修改。

Setter

Setter 是一个没有 getter 的虚拟属性类型。当我们在代码中设置该属性时,Mongoose 会执行 set 函数,并返回一个新的属性值。Setter 有一个非常重要的作用,它可以用来将外部数据格式化为符合 Schema 规范的格式。

下面的例子展示了一个字符串去除空格的 setter:

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

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

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

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

这个 setter 可以用来格式化一个消息,也可以用来进行格式校验或转换。Setter 属性还有一个重要的应用场景,就是用来处理外部 API 或者用户输入的数据,保证数据都符合指定格式。

虚拟属性选项

ref

在 Mongoose 中,虚拟属性可以通过 ref 选项关联到其他文档,从而实现文档间关联。ref 选项用来指定被关联文档的 model,支持 string 形式和 objectid 形式。

下面的例子展示了如何在 Mongoose 中关联两个文档:

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

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

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

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

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

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

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

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

这个例子展示了如何通过虚拟属性 ref 将 Customer 和 Order 关联起来。我们使用 localFieldforeignField 选项分别指定了关联的本地字段和外部字段。这样,我们就可以在查询 Customer 时直接获取它的订单列表。

localField 和 foreignField

在 ref 选项中,我们使用了两个额外的选项:localFieldforeignField。它们描述了两个文档间关联的字段。

  • localField:用于指定本 model(即虚拟属性所属的 model)中用于与外部 model 进行关联的字段名称。默认值为 '_id'。

  • foreignField:用于指定与外部 model 关联的字段名称(即外部 model 中要关联的字段)。默认值为 '_id'。

在关联两个文档时,我们经常需要在查询时使用 populate() 方法,这个方法可以将虚拟属性关联的文档一并查询出来,从而避免了多次查询带来的性能损失。

总结

虚拟属性是 Mongoose 中非常有用的功能,它可以用来处理文档间的关联、逻辑计算和数据格式转换等问题。在使用虚拟属性时,需要特别注意一些选项(如 reflocalFieldforeignField),以及虚拟属性类型(如 getter 和 setter)的区别。同时,还需要充分理解虚拟属性的特性和使用场景,以便更好的利用它们。

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

纠错
反馈