2

以下は、問題を示す関数です。

var mongoose = require('mongoose');
var connection = mongoose.createConnection('mongodb://localhost:27017');

connection.once('open', function () {
  var schema = new mongoose.Schema({
    obj: [{}] //mongoose.Schema.Types.Mixed
  });

  var Model = connection.model('mtest', schema);
  var model = new Model({
    obj: [{ name: 'Original' }]
  });

  model.save(function (err, res) {
    console.log('result 1', res);

    Model.findOne({_id: res._id}, function (err, res) {
      res.obj[0].name = 'Modified';
      res.obj.push({ name: 'other' });
      //res.markModified('obj'); // using markModified does not help

      res.save(function (err, res) {
        console.log('result 2', res);
        connection.close();
        process.exit();
      });
    });
  })
});

"result 2" の出力はModified、"obj": の最初の項目の " " を示していますobj: [ { name: 'Modified' }, { name: 'other' } ]。ただし、データベースでは、最初の項目の値はまだ " Original" です。

これは、2 番目の項目を配列にプッシュする場合にのみ発生します (そうでない場合、最初の項目は実際に変更されます)。追加markModifiedすると問題が解決します。

スキーマで空のオブジェクト型の配列を使用しています。実際には、このユース ケースは相互に継承するスキーマを扱うため、単一のスキーマをここで使用することはできません。

バグですか?私が見つけた唯一の回避策は、配列をクリアしてすべての項目を再度追加することです。より良い解決策があれば知りたいです。

4

1 に答える 1

1

markModified呼び出しを変更して、配列アクセス メソッドの「外側」で変更した要素のインデックスを識別することができます。

res.obj[0].name = 'Modified';
res.obj.push({ name: 'other' });
res.markModified('obj.0');

または、set配列アクセス メソッドを使用してアラートを送信するように切り替えますname(かなり間抜けに見えますが、機能します)。

res.obj[0].name = 'Modified';
res.obj.set(0, res.obj[0]);
res.obj.push({ name: 'other' });
于 2015-12-09T14:56:38.357 に答える