2012-10-02 72 views
0

我在命令行中使用MongoDB去遍历特定条件的一堆文档,从一个集合移动到另一个集合并从原始集合中移除。PHP MongoDB execute()锁定集合

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

这个工作,但是我需要剧本此所以它通过cron脚本会将所有文件中coll1删除收集每天(或每小时)来。我使用PHP,所以我想我会写一个脚本中使用PHP蒙戈图书馆::

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

这工作,但蒙戈命令行不同,DB->的execute()是evaled,这会导致锁定直到执行块完成,这会阻止对集合的所有写入。我在生产环境中无法做到这一点。

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

如果我使用:

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

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

有什么建议吗?

回答

2

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

正如你所说的最好的事情是做客户端。至于带宽,除非你得到了90年代以前的网络,那么相比于其他包括副本套件在内的其他一切使用的带宽,它很可能是非常少量的带宽。

你可以做的是在删除实际删除(在您的应用程序中)而不是每天一次后删除,然后每天一次通过原始集合删除所有删除的行。这样带宽将在整个一天内传播,并且在清理您的产品时,您只需执行一次删除命令。

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

虽然通常以这种方式删除仓库通常是比它值得的更多的工作。通常将它们保存在主集合中并在删除标记周围进行查询通常会更好(因为您可能已经做了这些操作而不是立即对其进行仓库处理)。

+0

谢谢你的回答和时间sammaye –