2012-10-02 104 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 –