在使用 Mongoose 进行 MongoDB 数据库操作的时候,我们通常会使用 schema 来定义数据模型。而在 schema 中,我们可以使用 virtual 来创建虚拟的属性,这些属性不会被保存到数据库中,但是可以在查询结果中返回。
然而,在使用 virtual 的过程中,可能会遇到一些问题,比如无法在 populate 中使用,或者在 toJSON 转换时无法输出。本文将介绍 Mongoose 中 schema 的 virtual 解决方法,帮助你更好地使用 virtual。
问题描述
在使用 virtual 的时候,可能会遇到下面两个问题:
- 无法在 populate 中使用
- 在 toJSON 转换时无法输出
下面分别介绍这两个问题的解决方法。
无法在 populate 中使用
在使用 populate 查询时,如果要查询的字段是 virtual 字段,那么查询结果中就不会包含这个字段。例如:
// javascriptcn.com 代码示例 const postSchema = new mongoose.Schema({ title: String, content: String, author: { type: mongoose.Schema.Types.ObjectId, ref: 'User' } }); const userSchema = new mongoose.Schema({ name: String, email: String }); userSchema.virtual('fullName').get(function() { return this.name + ' ' + this.email; }); const User = mongoose.model('User', userSchema); const Post = mongoose.model('Post', postSchema); Post.find().populate('author', 'fullName').exec((err, posts) => { console.log(posts); });
在上面的代码中,我们定义了一个虚拟的 fullName 字段,并且在 populate 中查询 author 字段的 fullName 属性。但是,输出的结果中并没有 fullName 字段。
这是因为 populate 查询是通过 MongoDB 的聚合操作实现的,而 virtual 字段并不是真正的字段,无法被聚合操作获取。为了解决这个问题,我们需要使用 Mongoose 的 toObject 和 toJSON 转换方法。
在 toJSON 转换时无法输出
在使用 toJSON 方法将 Mongoose 对象转换为 JSON 格式时,虚拟字段也无法被输出。例如:
// javascriptcn.com 代码示例 const postSchema = new mongoose.Schema({ title: String, content: String, author: { type: mongoose.Schema.Types.ObjectId, ref: 'User' } }); postSchema.virtual('summary').get(function() { return this.content.slice(0, 100); }); const Post = mongoose.model('Post', postSchema); Post.findOne((err, post) => { console.log(JSON.stringify(post)); });
在上面的代码中,我们定义了一个虚拟的 summary 字段,并且将 Post 对象转换为 JSON 格式输出。但是,输出的结果中并没有 summary 字段。
这是因为 toJSON 方法默认只输出 schema 中定义的字段,而不包括 virtual 字段。为了解决这个问题,我们需要在 schema 中添加一个选项,将 virtual 字段也包含进来。
解决方法
为了解决上面的两个问题,我们需要在 schema 中添加一个选项:toObject
和 toJSON
的 virtuals
属性。
// javascriptcn.com 代码示例 const postSchema = new mongoose.Schema({ title: String, content: String, author: { type: mongoose.Schema.Types.ObjectId, ref: 'User' } }, { toJSON: { virtuals: true }, toObject: { virtuals: true } }); postSchema.virtual('summary').get(function() { return this.content.slice(0, 100); }); const Post = mongoose.model('Post', postSchema); Post.findOne((err, post) => { console.log(JSON.stringify(post)); });
在上面的代码中,我们在 schema 的选项中添加了 toJSON
和 toObject
的 virtuals
属性,将 virtual 字段也包含进来。现在,再次运行代码,就可以看到输出结果中包含了 summary 字段。
另外,在使用 populate 查询时,我们也需要将 virtual 字段添加到查询结果中:
Post.find().populate('author', 'fullName').exec((err, posts) => { console.log(posts); }).then(() => mongoose.disconnect());
在上面的代码中,我们将 populate
方法的第二个参数改为 'fullName -_id'
,这样就可以查询到 author 的 fullName 字段了。
总结
在使用 Mongoose 中的 virtual 字段时,我们可能会遇到无法在 populate 中使用和在 toJSON 转换时无法输出的问题。为了解决这个问题,我们需要在 schema 中添加 toJSON
和 toObject
的 virtuals
属性,将 virtual 字段也包含进来。另外,在使用 populate 查询时,也需要将 virtual 字段添加到查询结果中。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65855a5cd2f5e1655d00136a