【问题标题】:I can't modify an array in Node我无法在 Node 中修改数组
【发布时间】:2017-12-23 15:55:21
【问题描述】:

我正在尝试对从 mongoose/MongDB 查询返回的数据数组进行一些修改。但是,我似乎无法对数组进行任何更改。我在这里遗漏了什么明显的东西吗?

function stdSend(err, data, res){
  if(err){
    console.log(err);
    res.send(err);
  }else{
    console.log('rows returned: ' + data.length);
    for(var rep=0;rep<data.length;rep++){
      var foo = new Date(data[rep].timestamp);   
      console.log(Object.isFrozen(data[rep]));    <- false
      console.log(Object.isSealed(data[rep]));    <- false
      data[rep].test = 'test';                    <- test not added to data[rep]
      data[rep].timestamp = foo;                  <- timestamp not modified
      console.dir(data[rep]);
    }
    //console.log(data);
    res.send(data);
  }
}

从 Mongoose .exec 函数调用 stdSend 作为回调。回调工作正常,数据在我将它提供给 Express 中的 res.send 后进入浏览器。但是,我想通过在发送数据之前将 data[].timestamp 值转换为标准日期时间值来进行一些快速的错误测试。

但是,我尝试更改数据值的一切都失败了。 data[rep].test = 'test' 无法将测试属性添加到数据,并且尝试修改时间戳也失败。 isFrozen 和 isSealed 都返回 false。

有什么想法吗?

编辑: 我认为我在这里问的内容有些混乱。我将数据写入数据库。这是从我试图修改的数据库查询返回的对象数组。返回的对象如下:

[ { name: 'scishow',
    timestamp: 1380154343818,
    funding: 42,
    subs: 3500 },
  { name: 'scishow',
    timestamp: 1380240748329,
    funding: 42,
    subs: 3520 },
  { name: 'scishow',
    timestamp: 1380327152521,
    funding: 42,
    subs: 3554 },
  { name: 'scishow',
    timestamp: 1380413558026,
    funding: 43,
    subs: 3579 },
  { name: 'scishow',
    timestamp: 1380585807946,
    funding: 43,
    subs: 3638 },
  { name: 'scishow',
    timestamp: 1384300959056,
    funding: 52,
    subs: 5 },
  { name: 'scishow',
    timestamp: 1384560752617,
    funding: 53,
    subs: 5 },
  { name: 'scishow',
    timestamp: 1384646717448,
    funding: 53,
    subs: 5 },
  { name: 'scishow',
    timestamp: 1384819280960,
    funding: 53,
    subs: 5 },
  { name: 'scishow',
    timestamp: 1385251243369,
    funding: 53,
    subs: 5753 },
  { name: 'scishow',
    timestamp: 1385338257810,
    funding: 53,
    subs: 5779 } ]

【问题讨论】:

    标签: node.js mongodb mongoose


    【解决方案1】:

    如果data 是 Mongoose 查询的结果,则它不是普通 JS 对象的数组,而是文档实例的数组。它们可能看起来像正确的 JS 对象,但你不能这样对待它们。

    您需要先将这些文档转换为正确的 JS 对象,然后才能更改它们:

    for (var rep = 0; rep < data.length; rep++) {
      var doc = data[rep].toObject();
      var foo = new Date(doc.timestamp);
      doc.test = 'test';
      doc.timestamp = foo;
      console.dir(doc);
    }
    

    或者,您可以将{ strict: false } 添加到您的架构中(如@HenryLeu 建议的那样)并在文档上使用.set() 来添加属性:

    data[rep].set('test', 'test');
    

    或者不改变你的架构:

    data[rep].set('test', 'test', { strict: false });
    

    【讨论】:

    • 该死,我花了差不多三个小时来调试这个,.set() 工作得很好。
    【解决方案2】:

    在您的猫鼬模式定义代码中。尝试使用选项strict: false 来启用设置和获取未定义的架构字段。默认情况下,stricttrue

    var thingSchema = new Schema({name: String, ...}, { strict: false});
    

    请参考mongoose docs about strict option

    【讨论】:

    • 这没有帮助。我没有写信给数据库。我正在修改从查询返回的数据,然后再将其发送到 Express 响应对象。
    【解决方案3】:

    @robertklep 的回答对我很有帮助,但是如果您尝试使用 EJS 呈现文档,您刚刚使用 .set() 附加的键:值将返回 undefined,因为 EJS 将 mongo 记录作为文档接收,而不是作为一个 JSON。

    因此,如果您不是在寻找 Mongo 文档而只是在寻找 JSON,则可以使用 .lean(),当与 .exec() 一起使用时,将返回 JSON 对象而不是 Mongo 文档。

    YOUR_MODEL.find()
    .lean().exec((err, data) => {
      if(err) throw err;
    
      //Assuming data will return something like [{myKey: val}, {myKey: val}]
    
      data.forEach((obj, idx) => {
        data[idx].myKey = 'alterValue';
      });
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-27
      • 2021-10-23
      • 2013-01-02
      • 1970-01-01
      • 2022-10-23
      • 2013-10-24
      • 2021-07-27
      • 1970-01-01
      相关资源
      最近更新 更多