更新:
- 删除了我的旧 map/reduce 方法,因为我发现(并且 Sammaye 指出)这会改变结构
- 使我的 exec 版本成为次要版本,因为我发现了如何使用 renameCollection 来做到这一点。
我相信我已经找到了解决办法。似乎某些版本的 PHP 驱动程序将针对 admin 数据库进行身份验证,即使它不需要这样做。但是有一种解决方法,其中 authSource 连接参数用于更改此行为,因此它不会针对 admin 数据库进行身份验证,而是针对您选择的数据库进行身份验证。所以现在我的 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();
}