0

我会尽量简洁——即使在异步调用 save() 部分时,Mongoose 似乎也不会保存记录,直到整个脚本结束:

var reallyBigData = require('./data.json');

var importData = function(data) {
  var newObj = new Obj; // Mongoose Object
  newObj.x = data.x;
  newObj.save();
};

this.on('importData', importData);

for(var i in reallyBigData) {
  this.emit('importData', reallyBigData[i]);
};

这是一个粗略的简化,但你明白了。当我运行脚本并查询 Mongo 时,我在脚本运行时看不到任何记录。如果我将数量限制为 30,然后导入它们,它会快速完成,然后我会看到记录。

为什么 Mongoose 在脚本执行时不保存每条记录?

4

2 回答 2

2

问题是x.save()(or newObj.save()) 是异步的,除了 Node 本身之外,你没有任何东西等待它完成。

由于是异步的,它只启动更新 MongoDB 中的集合的任务,然后立即退出。直到稍后调用可选回调时,它才会真正“完成”:

x.save(function (err, instance) {
    // at this point, it either erred or saved
});

不过,x.save()几乎可以立即完成。及时完成的​​记录数量较少意味着您有一个竞争条件——它将首先完成:对 MongoDB 或 Node/V8 的查询执行代码块?

而且,使用EventEmitter,至少您在这里对其进行采样的方式不足以使您的循环异步,因为您仍在emit同步处理事件并将同步emit()循环通过任何处理程序。

但是,有许多“控制流”库可以提供帮助。其中包括promisesfutures和 iterators 的实现,例如async

var reallyBigData = require('./data.json');

async.each(Object.keys(reallyBigData),
    function (key, callback) {
        new Obj({ x: reallyBigData[key] }).save(callback);
    },

    function (err, results) {
        // called with an `err` or an `Array` of `results` (saved `Obj`s)
    }
);
于 2013-03-08T21:13:33.970 回答
0

首先,我认为您在这里有一个令人讨厌的错误:

var importData = function(data) {
  var newObj = new Obj; // Mongoose Object
  Obj.x = data.x;
  x.save();
};

其中最有可能读作:

var importData = function(data) {
  var newObj = new Obj; // Mongoose Object
  newObj.x = data.x;
  newObj.save();
};

因为看起来您正在尝试对您的架构进行操作,而不是在您从架构中“新建”的模型上进行操作。那有意义吗?或者也许这就是你拥有它的方式,而你只是错过了输入?因为我看不到您将如何从现有代码中获得预期结果,无论它如何执行到数据库。也许正如您现在所拥有的那样,它正在努力检测模型是否已更改值,或者它未能通过您的验证。

于 2013-03-08T21:58:21.493 回答