获取对象数组中的每个嵌套对象的虚拟属性?

所以我知道如何获得一个单一的虚拟属性,如在Mongoose文档中所述:

PersonSchema .virtual('name.full') .get(function () { return this.name.first + ' ' + this.name.last; }); 

但是,如果我的模式是:

 var PersonSchema = new Schema({ name: { first: String , last: String }, arrayAttr: [{ attr1: String, attr2: String }] }) 

我想为arrayAttr中的每个嵌套对象添加一个虚拟属性:

 PersonSchema.virtual('arrayAttr.full').get(function(){ return attr1+'.'+attr2; }); 

我知道我是否错过了这里的东西。

您需要为attrArray的元素定义单独的模式,并将虚拟属性添加到该模式。

 var AttrSchema = new Schema({ attr1: String, attr2: String }); AttrSchema.virtual('full').get(function() { return this.attr1 + '.' + this.attr2; }); var PersonSchema = new Schema({ name: { first: String , last: String }, arrayAttr: [AttrSchema] }); 

当然,你可以定义一个额外的模式,但是mongoose已经在为你做这个了。

它存储在

 PersonSchema.path('arrayAttr').schema 

所以你可以通过把它添加到这个模式来设置一个虚拟的

 PersonSchema.path('arrayAttr').schema.virtual('full').get(function() { return this.attr1 + '.' + this.attr2 }) 

首先你应该写

this.some_attr而不是some_attr

你不能访问this.attr,因为在arrayAttr。 所以你可以做例如:

 this.arrayAttr[0].attr1 + "." + this.arrayAttr[0].attr2 

这是不安全的,因为arrayAttr可以是空的

如果你想要一个来自所有数组元素的计算值,这里是一个例子:

 const schema = new Schema({ name: String, points: [{ p: { type: Number, required: true }, reason: { type: String, required: true }, date: { type: Date, default: Date.now } }] }); schema.virtual('totalPoints').get(function () { let total = 0; this.points.forEach(function(e) { total += ep; }); return total; }); User.create({ name: 'a', points: [{ p: 1, reason: 'good person' }] }) User.findOne().then(function(u) { console.log(u.toJSON({virtuals: true})); }); 

返回到:

 { _id: 596b727fd4249421ba4de474, __v: 0, points: [ { p: 1, reason: 'good person', _id: 596b727fd4249421ba4de475, date: 2017-07-16T14:04:47.634Z, id: '596b727fd4249421ba4de475' } ], totalPoints: 1, id: '596b727fd4249421ba4de474' } 

我最喜欢的解决scheme是直接引用嵌套架构。

 PersonSchema.paths.arrayAttr.schema.virtual('full').get(function() { return this.attr1 + '.' + this.attr2; }); 

另外需要注意的是,缺省情况下,虚拟模式不会被mongoose模式返回。 因此,请确保在嵌套架构上设置string化属性。

 var options = { virtuals: true }; PersonSchema.paths.arrayAttr.schema.set('toJSON', options);