我在命令行上使用MongoDB来遍历一堆特定条件的文档,从一个集合移动到另一个集合并从原始集合中删除。
db.coll1.find({'status' : 'DELETED'}).forEach(
function(e) {db.deleted.insert(e); db.coll1.remove({_id:e._id}); });
然而,这需要编写脚本,因此它会通过cron脚本每天(或每小时)将coll1中的所有文档移动到已删除的集合中。我正在使用PHP,所以我想我会编写一个使用Mongo PHP Library ::
的脚本$db->execute('db.coll1.find({'status' :'DELETED'}).forEach(
function(e) { db.deleted.insert(e); db.coll1.remove({_id:e._id}); })');
这有效但与Mongo命令行不同,db-> execute()被唤醒,这会导致锁定,直到执行块完成,这将阻止对集合的所有写入。我不能在我的生产环境中这样做。
有没有办法(没有手动登录Mongo并运行命令)并通过PHP脚本执行它而不锁定?
如果我使用:
db->selectCollection('coll1')->find(array('status' => 'DELETED'))
并迭代我可以选择文档,保存到已删除的集合并从coll1集合中删除。然而,这似乎需要很多带宽来拉取客户端上的所有内容并将其保存回服务器。
有什么建议吗?
答案 0 :(得分:2)
有没有办法(没有手动登录Mongo并运行命令)并通过PHP脚本执行它而不锁定?
正如你所说,最好的办法是做客户端。至于带宽,除非你有一个90年代以前的网络,否则它很可能是一个非常小的带宽,相比你将用于其他一切,包括副本集等。
您可以做的是将删除内容实际删除(在您的应用中)而不是每天一次,然后每天一次,通过原始集合删除所有已删除的行。这样,带宽将在一天中传播,当涉及清理生产时,您只需执行一次删除命令。
另一种选择是使用MR并使其output
成为该集合。
虽然一般情况下,以这种方式删除仓库通常比工作更有价值。通常最好将它们保存在主集合中,并围绕已删除的标志进行查询(因为您可能已经做过不立即将它们存储起来)。