0

我在命令行上使用 MongoDB 来循环遍历一组特定条件的文档,从一个集合移动到另一个集合并从原始集合中删除。

db.coll1.find({'status' : 'DELETED'}).forEach(
    function(e) {db.deleted.insert(e);  db.coll1.remove({_id:e._id});  });

这可行,但是我需要编写脚本,以便每天(或每小时)通过 cron 脚本将 coll1 中的所有文档移动到已删除的集合中。我正在使用 PHP,所以我想我会编写一个使用 Mongo PHP 库的脚本::

$db->execute('db.coll1.find({'status' :'DELETED'}).forEach(
    function(e) {  db.deleted.insert(e); db.coll1.remove({_id:e._id});  })');

这可行,但与 Mongo 命令行不同,db->e​​xecute() 被评估,这会导致锁定直到执行块完成,这会阻止对集合的所有写入。我不能在我的生产环境中这样做。

有没有办法(无需手动登录 Mongo 并运行命令)并通过 PHP 脚本执行而不锁定?

如果我使用:

db->selectCollection('coll1')->find(array('status' => 'DELETED')) 

并遍历,我可以选择文档,保存到已删除的集合并从 coll1 集合中删除。然而,这似乎需要大量带宽来拉取客户端上的所有内容并将其保存回服务器。

有什么建议么?

4

1 回答 1

2

有没有办法(无需手动登录 Mongo 并运行命令)并通过 PHP 脚本执行而不锁定?

正如您所说,最好的办法是在客户端进行。至于带宽,除非您拥有 90 年代之前的网络,否则与您用于其他一切(包括副本集等)的带宽相比,它很可能是非常小的带宽。

您可以做的是在实际删除时(在您的应用程序中)存储您的删除,而不是每天一次,然后您将每天一次返回原始集合,删除所有已删除的行。这样一来,带宽将全天分布,在清理您的作品时,您只需执行一个删除命令。

另一种选择是使用 MR 并使其output成为该集合。

虽然一般来说,以这种方式进行仓储删除通常比它值得做的工作更多。通常最好将它们保留在您的主集合中并围绕已删除标志处理您的查询(因为您可能已经不立即存储这些)。

于 2012-10-02T07:51:58.057 回答