【问题标题】:What's the best way to modify every document in a large MongoDB collection without overloading memory?在不超载内存的情况下修改大型 MongoDB 集合中的每个文档的最佳方法是什么?
【发布时间】:2015-04-10 13:11:25
【问题描述】:

目前我正在运行这个任务:

var skip = 0;
var limit = 5;

gulp.task('add coordinates to visits', function(done) {

(function recurse() {

    Visit.find({})
        .skip(skip)
        .limit(limit)
        .populate('zone')

    .exec(function cb(err, visits) {
        if (err) {
            throw err;
        }
        if (visits.length === 0) {
            return;
        }

        async.each(visits, function iterateEvents(visit, next) {
            if (!visit.zone) {
                return next();
            } else if (!visit.coordinates.lat || !visit.coordinates.lng) {
                visit.coordinates = {
                    lat: visit.zone.geo.coordinates.lat,
                    lng: visit.zone.geo.coordinates.lng
                };
            }
            visit.save(next);

        }, function cb(err) {
            if (err) {
                throw err;
            }

            skip += limit;
            setTimeout(recurse, 1000);
        });

    });

})();

});

但我敢肯定,一定有比使用skiplimit、`setTimeout.是否有一些运行更新任务的 mongo 或 mongoose 方法?

【问题讨论】:

  • 您是否将这些文档保存回数据库?如果是这样,为什么不直接在数据库上更新?
  • 是的,我是。我不小心漏掉了visit.save(next);。您能否进一步解释您的评论。我该怎么做?
  • 可以直接使用Model.update对数据库进行查询和更新。
  • 但我仍然需要先查询数据库以获取要添加到访问中的 zone 数据。那么有什么优势呢?看看我如何填充区域,然后将该数据直接添加到访问。
  • 我错过了,但是否有任何区域不会被查询更新?这意味着您可以直接在 Zones 集合上运行类似的查询。

标签: node.js mongodb mongoose


【解决方案1】:

根据我们在 cmets 中的对话,Mongoose 的 querystream 可能就是您想要的:

var stream = Visits.find().populate('zone').stream();

stream.on('data', function processDoc(visit) {
  var self = this;

  if (visit.zone && (!visit.coordinates.lat || !visit.coordinates.lng)) {
    self.pause();

    visit.update({
      coordinates: {
        lat: visit.zone.geo.coordinates.lat,
        lng: visit.zone.geo.coordinates.lng
      }
    }, function(err, result) {
      if (err) { console.log(err); };
      self.resume();
    });
  }
});

stream.on('error', function(err) {
  console.log('error', err);
});

stream.on('close', function() {
  console.log('closed');
});

【讨论】:

  • 谢谢杰森。这就是我一直在寻找的。但是由于某种原因,当我填充该区域时,我无法让它工作。我收到此错误:MissingSchemaError: Schema hasn't been registered for model "zone"。使用我的旧方法没有这个问题。有什么想法吗?
  • Hmmmmm...这通常意味着模型在执行查询之前尚未注册。您能否在调用函数之前验证 Zone 模型是否可用?
  • 谢谢。你是对的。我的模型没有正确注册。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-24
  • 1970-01-01
  • 2022-09-27
  • 1970-01-01
  • 2020-02-20
  • 2022-06-16
相关资源
最近更新 更多