2013-07-22 35 views
7

PHP的Mongo驅動程序缺少renameCommand函數。 There is reference通過管理數據庫執行此操作。但是,如果沒有該數據庫的登錄權限,似乎更新版本的Mongo驅動程序不會讓您「使用」管理數據庫。所以這種方法不再有效。我也讀過,這在分片環境中不起作用,儘管目前這不是我關心的問題。在PHP中重命名Mongo Collection

其他人似乎有建議是遍歷「從」收集並插入到「收集」。用適當的WriteConcern(火和忘記),這可能會相當快。但它仍然意味着將每個記錄通過網絡拖入PHP進程,然後通過網絡將其上傳回數據庫。

我理想地想要一種方法來完成所有的服務器端。有點像SQL中的INSERT INTO ... SELECT ...。這種方式快速,網絡高效,PHP負載較低。

回答

0

更新

  • 打消了我的舊的map/reduce方法,因爲我發現了(和Sammaye指出),這改變了結構
  • 使我的EXEC版本次要,因爲我發現瞭如何通過renameCollection來完成。

我相信我找到了解決方案。它似乎有些版本的PHP驅動程序會對管理數據庫進行認證,即使它不需要。但是存在a workaround,其中authSource連接參數用於更改此行爲,因此它不會針對管理數據庫進行認證,而是針對您選擇的數據庫進行認證。所以現在我的renameCollection函數只是再次使用renameCollection命令的一個包裝。

關鍵是在連接時添加authSource。在下面的代碼中,$ _ENV ['MONGO_URI']保存我的連接字符串,而default_database_name()返回我要驗證的數據庫的名稱。

$class = 'MongoClient'; 
if(!class_exists($class)) $class = 'Mongo'; 
$db_server = new $class($_ENV['MONGO_URI'].'?authSource='.default_database_name()); 

這是我所使用的eval這也應該工作雖然有些環境不允許你給eval(MongoLab爲您提供了一個殘缺的設置,除非你有一個專用系統)舊版本。但是如果你在分散的環境中運行,這似乎是一個合理的解決方案。

function renameCollection($old_name, $new_name) { 
    db()->$new_name->drop(); 
    $copy = "function() {db.$old_name.find().forEach(function(d) {db.$new_name.insert(d)})}"; 
    db()->execute($copy); 
    db()->$old_name->drop(); 
} 
+0

MR將改變文檔結構的兩個集合之間,你應該可以,如果你有合適的身份驗證 – Sammaye

+0

是啊,「用」的管理數據庫,我意識到我張貼這種過早,因爲我沒注意到結構改變。我目前正在設法弄清楚如何在沒有減少部分的情況下進行地圖/縮減。 –

+0

這不是減少問題,但從根本上說,在內部,MongoDB如何形成結果文檔並將其寫出。事實上,你永遠不應該運行reduce,因爲你應該只返回一個關鍵文件,而MongoDBs reduce不會在這種情況下運行 – Sammaye

0

我剛纔測試了這一點,它的工作原理與設計(http://docs.mongodb.org/manual/reference/command/renameCollection/):

$mongo->admin->command(array('renameCollection'=>'ns.user','to'=>'ns.e')); 

那你是怎麼命名的unsharded集合。 MR的一個問題是它會改變原始集合的輸出形狀。因此,它不擅長複製收藏。如果你的收藏被分割,你最好手動複製它。

作爲一個附加說明,我升級到1.4.2(由於某種原因從pecl通道進入phpinfo()1.4.3dev :S),它仍然有效。

+0

這就是我以前做的事情。但是,由於我將mongo驅動程序升級到1.4.1,因此停止了對認證的抱怨。我有另一臺機器仍然在較早的mongo驅動程序上,它仍然工作,所以我知道這不是數據庫權限問題。 –

+0

@EricAnderson我在1.4.2上,我沒有得到那個問題 – Sammaye

+0

也許1.4.1具體。我發現與它有關的問題,它使用https://jira.mongodb.org/browse/PHP-782上的authSource提供解決方法。現在回到剛纔使用的renameCollection。感謝幫助我弄清楚了這一切。 –

-1

你可以使用這個。 「dropTarget」標誌爲true,則刪除存在的數據庫。

$mongo = new MongoClient('_MONGODB_HOST_URL_'); 
    $query = array("renameCollection" => "Database.OldName", "to" => "Database.NewName", "dropTarget" => "true"); 

    $mongo->admin->command($query); 
+0

這不解決問題。問題是renameCommand不能始終工作,這取決於憑據和Mongo驅動程序版本。使用dropTarget運行命令是我正在嘗試執行的操作。如果您對管理數據庫沒有特權或者正在使用某些版本的PHP mongo驅動程序,它並不總是有效。 –