用PHP重命名Mongo集合

时间:2013-07-22 17:20:07

标签: php mongodb

PHP的Mongo驱动程序缺少renameCommand函数。 There is reference通过管理数据库执行此操作。但是,如果没有对该数据库的登录权限,似乎更新版本的Mongo驱动程序不会让您“使用”管理数据库。所以这种方法不再适用。我也读过这在分片环境中不起作用,虽然这对我来说不是一个问题。

人们似乎有的另一个建议是迭代“from”集合并插入“to”集合。使用正确的WriteConcern(fire and forget),这可能相当快。但它仍然意味着将网络上的每条记录下载到PHP进程中,然后通过网络将其上传回数据库。

我理想地想要一种在服务器端执行此操作的方法。类似于SQL中的INSERT INTO ... SELECT ...这样就可以实现快速,网络效率和PHP的低负载。

3 个答案:

答案 0 :(得分: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的旧版本,虽然某些环境不允许你评估(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();
}

答案 1 :(得分:0)

我刚试过这个,它按设计工作(http://docs.mongodb.org/manual/reference/command/renameCollection/):

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

这就是你重命名一个未整理的集合的方法。 MR的一个问题是它将改变原始集合的输出形状。因此,它不是很擅长复制集合。如果你的收藏品是分片的,你最好手动复制它。

作为补充说明,我升级到1.4.2(由于某种原因从pecl通道输出到phpinfo()为1.4.3dev :S),它仍然有效。

答案 2 :(得分:-2)

你可以用它。 “dropTarget”标志为true,然后删除存在的数据库。

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

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