如何用Mongoose填充包含虚拟属性的嵌套文档?
问题
我定义了如下两个Mongoose Schema:
// foo.js ... const fooSchema = new Schema( { name: { type: String } }, { toJSON: { virtuals: true }, toObject: { virtual: true } } ); // sample virtual fooSchema.virtual('sampleVirtual').get(function () { return 'I am a virtual' }); export default mongoose.model( 'foo', fooSchema );
另一个Schema关联上述Schema:
// hello.js ... const helloWorldSchema = new Schema( { name: { type: String, required: true }, myFoo: { type: mongoose.Types.ObjectId, ref: 'foo' } }, { toJSON: { virtuals: true }, toObject: { virtual: true } } ); export default mongoose.model( 'HelloWorld', helloWorldSchema );
我使用Mongoose的findOne()方法查询helloWorldSchema集合的文档,尝试填充myFoo文档的虚拟属性sampleVirtual:
// get.js const retVal = await helloWorldModel .findOne({_id: <some-id> }) .populate({ path: 'myFoo', select: '_id name sampleVirtual' }) .exec(); console.log(retVal.myFoo.sampleVirtual) //undefined
请问我哪里操作出错了?
问题原因及解决办法
1. Schema配置拼写错误
两个Schema的toObject选项里,属性名写错成了virtual: true,正确的应该是virtuals: true(末尾带s)。这个配置控制文档转换成普通对象时是否包含虚拟属性,拼写错误会导致虚拟属性无法被正常输出。
2. Populate的select不能指定虚拟属性
虚拟属性是Mongoose运行时动态生成的,并非MongoDB中实际存储的字段,所以在populate的select参数里指定sampleVirtual是无效的,Mongoose会忽略这个不存在的字段。
修正后的代码
修正foo.js的Schema配置
// foo.js ... const fooSchema = new Schema( { name: { type: String } }, { toJSON: { virtuals: true }, toObject: { virtuals: true // 修正为virtuals } } ); // sample virtual fooSchema.virtual('sampleVirtual').get(function () { return 'I am a virtual' }); export default mongoose.model( 'foo', fooSchema );
修正hello.js的Schema配置
// hello.js ... const helloWorldSchema = new Schema( { name: { type: String, required: true }, myFoo: { type: mongoose.Types.ObjectId, ref: 'foo' } }, { toJSON: { virtuals: true }, toObject: { virtuals: true // 修正为virtuals } } ); export default mongoose.model( 'HelloWorld', helloWorldSchema );
修正get.js的查询代码
// get.js const retVal = await helloWorldModel .findOne({_id: <some-id> }) .populate({ path: 'myFoo', select: '_id name' }) // 移除无效的sampleVirtual .exec(); console.log(retVal.myFoo.sampleVirtual) // 现在会输出"I am a virtual"
内容的提问来源于stack exchange,提问作者V. Pravi
相关产品推荐
相关产品推荐

