【问题标题】:Enforce limit on mongodb bulk API对 mongodb 批量 API 实施限制
【发布时间】:2016-05-07 17:01:58
【问题描述】:

我想从一个集合中删除大量旧文档,因此使用批量 API 是有意义的。删除它们很简单:

var bulk = db.myCollection.initializeUnorderedBulkOp();

bulk.find({
  _id: {
    $lt: oldestAllowedId
  }
}).remove();

bulk.execute();

唯一的问题是这将尝试删除每个符合此条件的文档,在这种情况下是数百万个文档,因此出于性能原因,我不想一次全部删除它们。我想对操作实施限制,以便我可以执行bulk.limit(10000).execute(); 之类的操作,并将操作间隔几秒钟,以防止锁定数据库的时间超过必要的时间。但是,我一直找不到任何可以传递给 bulk 以限制其执行次数的选项。

有没有办法以这种方式限制批量操作?

在任何人提到它之前,我就知道批量操作会自动将操作拆分为 1000 个文档块,但它仍会尽可能快地按顺序执行所有这些操作。这导致的性能影响比我现在可以处理的要大得多。

【问题讨论】:

  • 您尝试bulk.find({...}).limit(10000).remove(); 是否像普通查询/光标一样?
  • Nvm。刚试了一下,批量不行。
  • Markus,我完全可以使用.remove(),这就是我这次要做的事情,但我想知道是否可以对批量执行限制以获得更好的批量操作性能。

标签: node.js mongodb mongodb-query


【解决方案1】:

您可以使用.forEach 方法迭代与您的查询匹配的那些文档的_id 数组。返回该数组的最佳方法是使用.distinct() 方法。然后,您可以使用 "bulk" 操作删除您的文档。

var bulk = db.myCollection.initializeUnorderedBulkOp();
var count = 0;

var ids = db.myCollection.distinct('_id', { '_id': { '$lt': oldestAllowedId } } );

ids.forEach(function(id) {
    bulk.find( { '_id': id } ).removeOne();
    count++;
    if (count % 1000 === 0) {
        // Execute per 1000 operations and re-init
        bulk.execute();
        // Here you can sleep for a while 
        bulk = db.myCollection.initializeUnorderedBulkOp();
    }
});

// clean up queues
if (count > 0 ) {
    bulk.execute();
}

【讨论】:

  • 这是可能的,但实际上使用var ids = db.collection.find(query, {_id:1}) 然后bulk.find({$in: ids}).remove() 效率更高,但我真的很好奇我是否可以在一次批量操作中完成所有这些操作。
  • @RobRiddle 不!这是因为无法使用Bulk API 限制文档数量。你也应该使用distinct 来返回_id 的数组,因为_id 是唯一的。
  • Find 永远不会返回 _id 的重复结果,因为它是 mongo 的默认唯一索引,因此该查询不需要 mongo distinct 提供的任何额外逻辑。如果它是一个不同的领域,它可能是。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-05
  • 2016-10-26
  • 2013-05-21
  • 2018-05-21
  • 2015-05-13
  • 1970-01-01
相关资源
最近更新 更多