在 Mongoose 中,Virtual 可以用来创建虚拟属性,这些属性不会被保存到数据库中,但可以被查询和使用。在本文中,我们将会详细讲解如何使用 Mongoose 中的 Virtual 属性,以及与其相关的问题和注意事项。
Virtual 属性的用途
Virtual 属性可以在需要时动态地从已有属性中衍生出新的属性,这是非常有用的。例如,假设我们有一个文档模型,其中包含了一个 name 和一个 surname 字段,我们可以使用 Virtual 来实现 fullName 属性的自动创建。这个属性可以通过将 name 和 surname 的值合并而生成,而且不需要在数据库中保存。
创建 Virtual 属性
在 Mongoose 中创建 Virtual 属性非常简单。假设我们有一个用户模型,包含如下字段:
const UserSchema = new Schema({
name: String,
surname: String
});我们可以在模型中添加如下代码来创建 Virtual:
UserSchema.virtual('fullName').get(function() {
return `${this.name} ${this.surname}`;
});在这个例子中,fullName 是我们即将创建的虚拟字段名。我们通过 get 函数定义了这个字段的计算方法。在这个例子里,我们返回将 name 和 surname 字段的值拼接在一起的字符串。需要注意的是,当我们使用虚拟字段时,fullName 不应该出现在真正的数据存储中。
使用 Virtual 属性
使用 Virtual 属性是非常简单的,只需要像其他属性一样使用即可。例如,我们可以像下面这样查询一个用户的全名:
const user = await User.findOne({ _id: someId });
console.log(user.fullName);在这个例子中,我们查询了一条用户信息,并且通过 user.fullName 访问到这个用户的全名。
需要注意的是,虚拟属性的这种访问方式只适用于读取数据。如果我们想要在查询中使用虚拟属性进行过滤或排序,这是行不通的。在这种情况下,我们需要在模型中添加一个真实的字段来保存虚拟属性的结果。
保存 Virtual 属性
如果我们想要在查询中使用虚拟属性进行过滤或排序,我们需要存储虚拟属性的结果。为此,我们可以在模型中添加如下代码来创建一个真实字段:
// www.javascriptcn.com code example
UserSchema
.virtual('fullName')
.get(function () {
return `${this.name} ${this.surname}`;
})
.set(function (fullName) {
const [name, surname] = fullName.split(' ');
this.name = name;
this.surname = surname;
});在这个例子中,我们通过 setter 函数定义了如何保存虚拟属性的结果到数据库。在这个例子里,我们将传入的 fullName 参数分解成 name 和 surname,并将它们保存到真实的 name 和 surname 字段中。
需要注意的是,这种方式需要将虚拟属性设置为可用于存储,同时将 UserModel 的 schema 设为toJSON:{virtuals:true}或toObject:{virtuals:true}以便Virtual属性可以出现在结果中。
注意事项
当使用 Virtual 属性时,我们需要注意以下几点:
- 虚拟属性没有实际保存到数据库中,它只是在查询时从真实字段衍生出来的;
- 虚拟属性不能用于过滤和排序,因为它们不存在于数据库中;
- 如果想把虚拟属性用于过滤和排序,需要在模型中添加一个真实字段保存虚拟属性的结果;
- 如果想让虚拟属性在返回结果时被包含在内,需要将 UserModel 的 schema 设为 toJSON:{virtuals:true} 或 toObject:{virtuals:true};
示例代码
下面是一个使用 Virtual 属性的例子:
// www.javascriptcn.com code example
const mongoose = require('mongoose');
const UserSchema = new mongoose.Schema({
name: String,
surname: String
});
UserSchema.virtual('fullName').get(function() {
return `${this.name} ${this.surname}`;
});
UserSchema
.virtual('fullName')
.get(function () {
return `${this.name} ${this.surname}`;
})
.set(function (fullName) {
const [name, surname] = fullName.split(' ');
this.name = name;
this.surname = surname;
});
UserSchema.set('toJSON', { virtuals: true });
const User = mongoose.model('User', UserSchema);在这个例子中,我们创建了一个用户模型,并添加了 fullName 虚拟属性。这个属性在读取时可以被直接查询,以及在返回结果时被包含在内。我们还在模型中添加了 fullName 真实字段,以便在查询时可以使用,同时在自动生成时不会使用。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67d7f00fa941bf7134e2f9ae