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

时间:2012-11-29 16:51:07

标签: node.js mongodb express mongoose

所以我知道如何获得单个虚拟属性,如Mongoose docs中所述:

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;
});

Lemme知道我在这里错过了什么。

5 个答案:

答案 0 :(得分:23)

您需要为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]
});

答案 1 :(得分:6)

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

存储在

PersonSchema.path('arrayAttr').schema

因此,您可以通过将虚拟添加到此架构来设置虚拟

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

答案 2 :(得分:2)

如果您想要所有数组元素的计算值,请参见以下示例:

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 += e.p;
    });
    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' }

答案 3 :(得分:0)

首先你应该写

this.some_attr代替some_attr

你无法访问this.attr,因为arrayAttr中有。所以你可以这样做:

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

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

答案 4 :(得分:-1)

我最喜欢的解决方案是直接引用嵌套模式。

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

值得注意的是,默认情况下,mongoose模式不会返回虚拟。因此,请确保在嵌套模式上设置字符串化属性。

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