如何强制Mongoose Save()调用是同步的

时间:2014-05-31 10:32:36

标签: javascript mongodb mongoose

我在Node.js中编写一个脚本,需要执行以下操作:

  1. 打开XML文件
  2. 对于文件中的每个节点
  3. 执行mongodb查找以尝试查找与此节点相关的对象
  4. 如果找不到对象,则创建它,否则以某种方式操作找到的对象
  5. 将(可能是新的)对象保存回数据库。
  6. 转到第2步
  7. 我已经看了一段时间并得出结论,使用异步mongodb几乎不可能做到这一点。问题是多方面的,但是例如,如果您正在处理20,000个这样的节点,那么执行异步将挂起脚本。但是,由于步骤4需要查看对象是否已存在,因此将它们作为批量插入进行操作是不可行的。

    有可能将一些可怕的东西拼凑在一起来缓存创建的对象,然后将它们保存为类似于步骤7的东西,除非它很难,因为对象进入了多个集合,你需要尝试首先从缓存中查找对象,然后在步骤4中查找数据库。如果这是解决方案,那么我将把Javascript写为已损坏并在perl中写入此内容。所以我的问题是,对于像上面的动作序列这么简单的事情,我能不能以某种方式强制 mongodb同步,以便我的脚本不会变成疯狂?我希望能够说出document.save()(顺便说一下,我使用的是Mongoose),然后让它在实际保存之后才会返回。

    修改:添加了代码

    这是从一个循环调用大约20000次。我不在乎(在合理范围内)需要多长时间,但是200,000异步调用保存会使脚本挂起,因此它不会那样(它在那时也使用超过1.5g的ram)。如果我不能使 hObj.save(); 等到对象实际保存,那么我将需要用更有能力的语言来编写它。

        models('hs').findOne({name: r2.$.name}, function (err, h) {
        if (err) {
            console.log(err);
        } else {
            var resultObj = createResult(meeting, r1, r2);
    
            if (h == undefined) {
    
                var hObj = new models('hs')({
                    name : r2.$.name,
                    results : [resultObj],
                    numResults : 1
                });
    
                hObj.save();
            } else {
                h.results.push(resultObj);
                h.numResults++;
                h.save();
            }
        }
    });
    

1 个答案:

答案 0 :(得分:6)

来自async github页面:

  

eachSeries (arr,iterator,callback)

     

与每个项目相同,只有迭代器应用于arr in中的每个项目   系列。下一个迭代器仅在当前迭代器调用时调用   完成。这意味着迭代器函数将按顺序完成。

假设您在节点

中拥有XML节点
async.eachSeries(
  nodes,
  // This will be applied to every node in nodes
  function (node, callback) {
    models('hs').findOne({name: r2.$.name}, function (err, h) {
      if (err) {
        console.log(err);
      } else {
        // Async?
        var resultObj = createResult(meeting, r1, r2);

        if (h == undefined) {

          var hObj = new models('hs')({
            name : r2.$.name,
            results : [resultObj],
            numResults : 1
          });

          hObj.save(function (err, p) {
            // Callback will tell async that you are done
            callback();
          });
        } else {
          h.results.push(resultObj);
          h.numResults++;
          h.save(function (err, p) {
            // Callback will tell async that you are done
            callback();
          });
        }
      }
    });
  },
  // This will be executed when all nodes has been processed
  function (err) {
    console.log('done!');
  }
);