【问题标题】:get virtual attribute for each nested object in an array of objects?获取对象数组中每个嵌套对象的虚拟属性?
【发布时间】:2012-11-17 19:34:05
【问题描述】:

所以我知道如何获取单个虚拟属性,如 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;
});

如果我错过了什么,请告诉我。

【问题讨论】:

    标签: node.js mongodb express mongoose


    【解决方案1】:

    首先你应该写

    this.some_attr 而不是some_attr

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

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

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 没有额外的架构就没有办法做到这一点?或者我应该说,额外的嵌入式架构
      • @deusj 我不知道,没有。​​
      【解决方案3】:

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

      它存储在

      PersonSchema.path('arrayAttr').schema
      

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

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

      【讨论】:

      • 如果arrayAttr 是一个对象数组。这是指哪个对象?还是full 现在是arrayAttr 内每个对象的新属性或键?
      • full 是每个 arrayAttr 对象上的一个新虚拟属性。
      • 好东西!!但是,我仍然在努力使这个文件出现在 JSON 中。我试图添加Schema.path('items').schema.toJSON = { virtuals: true };,但在父级的toJSON ret 值仍然错过它。
      • 更新:Schema.path('items').schema.options.toJSON = { virtuals: true };,现在可以使用了
      【解决方案4】:

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

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

      【讨论】:

        【解决方案5】:

        如果你想从所有数组元素中计算出一个值,这里有一个例子:

        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' }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-10-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-11-27
          • 1970-01-01
          相关资源
          最近更新 更多