在 Mongoose 中定义虚拟属性时遇到的 bug 及解决方案
Mongoose 是一个在 Node.js 运行环境下,操作 MongoDB 数据库的 ODM(Object Document Mapping)工具,被广泛应用于 Node.js Web 应用的开发中。在 Mongoose 模型中,虚拟属性是一种非常实用的工具,它可以通过 JavaScript 中的 getter 和 setter 来处理模型实例的一些特殊需求。然而,在使用 Mongoose 定义虚拟属性时,我们也可能会遇到一些 bug。
本文将介绍在 Mongoose 中定义虚拟属性时遇到的一个 bug,并提供解决方案和示例代码供参考。希望本文能够对开发人员在 Mongoose 中应用虚拟属性有所帮助。
遇到的 Bug
在 Mongoose 中,定义虚拟属性的一般用法如下:
-- -------------------- ---- -------
----- ------------ - --- -----------------
----- -
------ -------
----- ------
-
---
----------------------------------------------- -
------ ------------------- -------------------
---上面的代码中,定义了一个 Person 模型,其中 name 属性是一个对象,包含了 first 和 last 两个属性。虚拟属性 fullName 的 getter 函数返回了一个拼接了 first 和 last 属性值的字符串。
然而,假如 Person 模型中的 name 属性是在一个嵌套的子文档中定义的,那么上面的代码就会出现问题。例如:
-- -------------------- ---- -------
----- ------------ - --- -----------------
----- -
------ -------
----- ------
--
-------- -
------- -------
----- -------
------ -------
---- ------
-
---
-------------------------------------------------- -
------ ----------------------- --------------------- --------------------- ---------------------
---上面的代码中,又新增了一个 address 属性,它是一个嵌套的子文档。虚拟属性 fullAddress 的 getter 函数返回了一个拼接了 address 属性中所有字段值的字符串。
上面的代码看起来没什么问题,但是当我们在程序中实际使用这个 fullAddress 属性时,就会发现它的值始终为 undefined。
解决方案
问题的原因是虚拟属性的 getter 函数中的 this 关键字并不是指向模型实例本身,而是指向了一个 Mongoose 内部的对象。这个内部对象和模型实例有着相同的属性和方法,但是并不会包含模型实例的子文档属性。因此,当模型实例中包含了子文档属性时,我们就需要手动将 this 关键字指向正常的模型实例对象。
针对这个问题,Mongoose 官方文档提供了如下解决方案:
personSchema.virtual('fullAddress').get(function() {
return `${this.address.street} ${this.address.city}, ${this.address.state} ${this.address.zip}`;
}).getters.unshift(function() {
return this.$parent.fullAddress;
});上面的代码在定义虚拟属性 fullAddress 时,为其添加了一个 getter 函数。这个 getter 函数使用了 Mongoose 中的 getters 数组,将 this 关键字指向了该属性的父级对象。通过这种方式,就能够得到包含所有子文档属性的 fullAddress 值了。
示例代码
下面是一个模型定义的完整示例代码,其中定义了包含子文档属性的虚拟属性和正确的 getter 函数。
-- -------------------- ---- -------
----- -------- - --------------------
----- ------ - ----------------
----- -------- - ----------------
----- ------------ - --- -----------------
----- -
------ -------
----- ------
--
-------- -
------- -------
----- -------
------ -------
---- ------
-
---
-------------------------------------------------- -
------ ----------------------- --------------------- --------------------- ---------------------
----------------------------- -
------ -------------------------
---
----- ------ - ------------------------ --------------
----- ------ - --- --------
----- - ------ ------- ----- ----- --
-------- - ------- ---- ---- ----- ----- ---------- ------ ----- ---- ------- -
---
-------------------------------- -- ---- ---- ---- --- -------- -- ------结语
虚拟属性是 Mongoose 中非常实用的功能之一,通过 getter 和 setter 函数,我们可以轻松地对模型实例进行自定义操作。然而,当虚拟属性包含了子文档属性时,我们需要注意到内部实现中的问题,才能正确地使用这个功能。在这篇文章中,我们介绍了在 Mongoose 中定义虚拟属性时遇到的 bug,以及解决方案和示例代码。希望这篇文章能够对你在开发中遇到类似问题时有所帮助。
Source: FunTeaLearn,Please indicate the source for reprints https://funteas.com/post/678067f2ce7f4861253a8732