如何重命名MongoDB数据库?

589

我的 MongoDB 数据库名中有一个错别字,我想要重命名该数据库。

我可以像这样 复制 并删除...

db.copyDatabase('old_name', 'new_name');
use old_name
db.dropDatabase();

是否有重命名数据库的命令?


7
从MongoDB 4.2版本开始,即使是copyDatabase命令也被弃用了。 - Sumit Ramteke
12个回答

439

如果你正在使用MongoDB < 4.2 (参考),你可以这样做:

db.copyDatabase("db_to_rename","db_renamed","localhost")
use db_to_rename
db.dropDatabase();

编辑说明:这是与问题本身相同的方法,但已经被其他人证明是有用的。


44
第三个参数实际上可以省略,它将默认为相同的服务器。 - Haakon
23
请注意,当 db_to_rename 和 db_renamed 只有大小写不同时,此方法将无法正常工作。在这种情况下,您需要使用临时数据库。(我刚遇到了这个问题 :)) - Sebastiaan M
76
这与OP提供的解决方案有何不同? - Salvador Dali
6
请问需要翻译的内容是:"this is same as the actual Question with the only difference being the third argument in copyDatabase method" 吗?如果是,我的翻译如下:这与实际问题相同,唯一的区别在于 copyDatabase 方法的第三个参数。 - Gurbakhshish Singh
17
除了几乎是从原问题的示例中复制粘贴以外,这段内容还存在一个问题,即在4.0版本之后它已经无效且不可用,因为他们完全删除了copyDatabase。请参考我的答案获取当前和现代的方法。 - amcgregor
显示剩余10条评论

327

另一种解决方案:您可以转储数据库并将其恢复到不同的名称。 从我的经验来看,这比 db.copyDatabase()快得多。

<code>$ mongodump -d old_db_name -o mongodump/
$ mongorestore -d new_db_name mongodump/old_db_name
</code>

http://docs.mongodb.org/manual/tutorial/backup-with-mongodump/


这是针对数据库重命名的当前官方推荐方法,考虑到copyDatabase在MongoDB 4.2中已被移除

“copydb”命令已经过时,请改用以下两个命令:

  1. mongodump(备份数据)
  2. mongorestore(从mongodump中恢复数据到新命名空间)

7
这样做更快,并且“附带效果”是,您的数据库也被压缩了。 - Comtaler
1
太好了!我已经创建了一个 mongodump。不知道你可以用不同的名称还原它。谢谢! - Dushyant Bangal
6
注意:如果你使用 --gzip 并创建一个存档文件,这个方法不会起作用。 - Dushyant Bangal
15
现在推荐使用这种方式,因为db.copyDatabase()已经被弃用。 - osolmaz
5
注意到,--db(-d)参数本身也已经被弃用。看起来有一些弃用的事情正在进行中,给定 copyDatabase 也被删除了。我已经用我的笔记戳了 SERVER-701 - amcgregor
显示剩余4条评论

235
没有这个功能。请参见 https://jira.mongodb.org/browse/SERVER-701
不幸的是,对于我们来说,这不是一个简单的功能,因为数据库元数据在原始(默认)存储引擎中的存储方式。在 MMAPv1 文件中,描述每个集合和索引的命名空间(例如:dbName.collection)包括数据库名称,因此要重命名一组数据库文件,必须重新编写每个命名空间字符串。这会影响到:
- .ns 文件 - 每个集合的每个编号文件 - 每个索引的命名空间 - 每个集合和索引的内部唯一名称 - system.namespaces 和 system.indexes 中的内容(或者将来的等价物) - 我可能漏掉的其他位置
这只是为了在< strong>独立 mongod 实例中重命名单个数据库。对于副本集,上述工作需要在每个副本节点上完成,在每个节点上,引用此数据库的每个 oplog 条目都必须被某种方式无效或重写,然后如果它是分片群集,则还需要将这些更改添加到每个 shard 上,如果数据库已分片,则配置服务器具有所有分片元数据以及其完整名称的命名空间。
没有任何方法可以在运行的系统上执行此操作。
要离线执行此操作,需要重新编写每个数据库文件以适应新名称,在那时它将与当前的 "copydb" 命令一样慢...

6
这个票据已经开了很长时间了。我已经在本来就很长的列表上添加了我的不太重要的投票。 - DJ van Wyk
5
他们构建数据库的方式和解释,似乎改名是不可能的 - 可能需要全新的架构。看起来像是一个巨大的疏忽,但在爱情、战争和软件开发中,一切都是公平的。 - serraosays
那么MongoDB应该有一个调用两个函数的命令,即复制和删除?我不认为有必要有这个单一的命令。但对某些人来说可能会很方便。 - TamusJRoyce
7
当你开始命名数据库时,应该只是一个内部名称的别名,Mongo 使用全局唯一的命名约定来生成这个名称。这样,更改数据库名称就像更改别名并将其传播到群集中的所有节点一样简单。我说“应该”如此,但事实并非如此。 - Lonnie Best
1
那太过分了 - Bernardo Dal Corno
1
@Bernardo Del Corno 完全同意。MongoDB就像一辆闪亮迷人的汽车。但当你坐在驾驶座上时,你会发现一切都有点奇怪。你可以向右打方向灯,但不能向左。踩油门会把音量调高。摇下车窗会导致发动机过热,直到冷却下来才能重新启动。每当你认为已经掌握了这辆车的规律,又会有新的问题出现。来源:与MongoDB共事7年,其中大部分是专业工作。 - Contango

31

注意:希望这在最新版本中已经改变了。

无论 FCV 值如何,您都不能在 MongoDB 4.0 mongod 实例和 MongoDB 3.4 及更早版本的 mongod 实例之间复制数据。 https://docs.mongodb.com/v4.0/reference/method/db.copyDatabase/

警告:拷贝数据库时要小心,以免搞乱单个数据库下的不同集合。

以下内容展示如何重命名

> show dbs;
testing
games
movies

要重命名,您可以使用以下语法

db.copyDatabase("old db name","new db name")

例子:

db.copyDatabase('testing','newTesting')

现在,您可以通过以下方式安全地删除旧的数据库

use testing;

db.dropDatabase(); //Here the db **testing** is deleted successfully

现在想象一下,如果你试图将新数据库名称重命名为现有数据库名称会发生什么

例如:

db.copyDatabase('testing','movies'); 

因此,在这个情境下,所有测试的集合(表)都将被复制到电影数据库。


4
copyDatabase 命令已经被移除。我已经使用自己的笔记在 SERVER-701 上进行了反馈。 - amcgregor
@amcgregor 谢谢您的通知。我已经添加了一条评论。希望它能帮助到某些人。 - Channaveer Hakari
1
db.copyDatabase在mongodb 4.4上已经不再使用。 - Dee
@datinhquoc 嗯,我已经将其作为注释添加了。 - Channaveer Hakari

28
从4.2版本开始,copyDatabase已被弃用,现在我们应该使用mongodumpmongorestore

假设我们有一个名为old_name的数据库,我们想要将其重命名为new_name

首先我们需要转储数据库:

mongodump --archive="old_name_dump.db" --db=old_name

如果您需要作为用户进行身份验证,请使用:

mongodump -u username --authenticationDatabase admin \
          --archive="old_name_dump.db" --db=old_name

现在我们把数据库导出成一个名为old_name_dump.db的文件。

如果要用新的名称进行恢复:

mongorestore --archive="old_name_dump.db" --nsFrom="old_name.*" --nsTo="new_name.*"

如果需要进行身份验证,请在命令中添加以下参数:

-u username --authenticationDatabase admin 

参考资料:https://docs.mongodb.com/manual/release-notes/4.2-compatibility/#remove-support-for-the-copydb-and-clone-commands


5
不必使用归档文件,您可以使用标准输出作为管道重命名。命令如下:mongodump --archive --db=old_name | mongorestore --archive --nsFrom='old_name.*' --nsTo='new_name.*' - a_manfrinati

20
虽然Mongodb没有提供重命名数据库的命令,但它提供了重命名集合命令,该命令不仅可以修改集合名称,还可以修改数据库名称。
{ renameCollection: "<source_namespace>", to: "<target_namespace>", dropTarget: <true|false>,  writeConcern: <document> }

db.adminCommand({renameCollection: "db1.test1", to: "db2.test2"})

这个命令只修改元数据,成本非常小,我们只需要遍历 db1 下的所有集合,将其重命名为 db2 以实现重命名数据库名称。
你可以在这个 Js 脚本中完成。
var source = "source";
var dest = "dest";
var colls = db.getSiblingDB(source).getCollectionNames();
for (var i = 0; i < colls.length; i++) {
var from = source + "." + colls[i];
var to = dest + "." + colls[i];
db.adminCommand({renameCollection: from, to: to});
}

使用此命令时要小心。

renameCollection 对目标命名空间有不同的性能影响。

如果目标数据库与源数据库相同,renameCollection 只会更改命名空间。这是一个快速操作。

如果目标数据库与源数据库不同,renameCollection 会将所有文档从源集合复制到目标集合。根据集合的大小,这可能需要更长的时间来完成。


索引和其他元数据怎么样?它们会被维护还是丢失了? - Udit Bhardwaj
@UDB 很可能被保留。 "重命名集合" 是一个 _命名空间转换_,基本上你的 bar 数据库中名为 foo 的集合具有命名空间 bar.foo。 因此 _id 上的索引具有命名空间 bar.foo._id_。 重命名集合(应该)在其知道的所有命名空间上执行前缀搜索和替换,类似于 mongorestore--nsFrom--nsTo 选项 - amcgregor
4
成本可能是巨大的!如果目标数据库与源数据库相同,renameCollection只是更改命名空间。这是一个快速的操作。如果目标数据库与源数据库不同,renameCollection将所有文档从源集合复制到目标集合。根据集合的大小,完成此操作可能需要更长的时间。 - nagylzs
请修改您的答案。您的答案很有帮助,因为可以使用此命令将集合移动到另一个数据库。但是它是不正确的,可能会误导他人。 - nagylzs

16
目前没有重命名数据库的机制。在撰写本文时接受的答案在事实上是正确的,并提供了一些有趣的背景细节,解释了上游的借口,但没有提供复制行为的建议。其他回答指向copyDatabase,但该功能在4.0中已被删除,不再是一个选项。我已经用我的笔记和怀疑更新了SERVER-701
等效行为涉及在mongodumpmongorestore之间进行一些操作:
  1. 导出数据时,要注意使用的“命名空间”。例如,在我的一个数据集中,我有一个带有命名空间byzmcbehoomrfjcs9vlj.Analytics的集合——这个前缀(实际上是数据库名称)将在下一步中需要。

  2. 导入数据时,提供--nsFrom--nsTo参数。(文档。) 继续以上假设(非常难读)的例子,为了恢复到一个更有意义的名称,我调用:

mongorestore --archive=backup.agz --gzip --drop \
    --nsFrom 'byzmcbehoomrfjcs9vlj.*' --nsTo 'rita.*'

有些人可能会指向mongorestore的--db参数,然而这也已经弃用,并且在非BSON文件夹备份上触发警告,完全错误地建议使用--nsInclude代替。上述命名空间转换等同于使用--db选项,并且是正确的命名空间操作设置,因为我们不尝试过滤正在恢复的内容。

4
截至2020年,mongodump与nsFrom/To是官方答案。 - PaoloC
4
amcgregor 提供的文档部分还提供了一个使用管道的简单例子:mongodump --archive --db=test | mongorestore --archive --nsFrom='test.*' --nsTo='examples.*' - konkit

9
上述过程较慢,您可以使用以下方法,但需要逐个将集合移动到另一个数据库。
use admin
db.runCommand({renameCollection: "[db_old_name].[collection_name]", to: "[db_new_name].[collection_name]"})

非常好的建议,在我看来。然而,值得注意的是,这不会释放原始数据库中的空间,但重命名应该比复制数据快得多。 - sirfz
2
算了,它确实会复制(因为它不会删除空格,所以这并不是一个简单的重命名),所以这种方法与复制和粘贴相比没有真正的优势。 - sirfz

6

我尝试做。

db.copyDatabase('DB_toBeRenamed','Db_newName','host') 

我得知它由Mongo社区已被废弃,虽然它可以创建备份或重命名数据库。

WARNING: db.copyDatabase is deprecated. See http://dochub.mongodb.org/core/copydb-clone-deprecation
{
        "note" : "Support for the copydb command has been deprecated. See 
        http://dochub.mongodb.org/core/copydb-clone-deprecation",
        "ok" : 1
}

对于上述方法,我并不太满意,因此我不得不使用以下命令来获取本地Dump。

mongodump --host --db DB_TobeRenamed --out E://FileName/

已连接到数据库。

use DB_TobeRenamed

然后
db.dropDatabase()

然后使用命令还原了数据库。

mongorestore -host hostName -d Db_NewName E://FileName/

这是基于弃用文档的官方方法。 - Mat Lipe

4

如果您把所有数据都放在管理员数据库中(不应该这样做),您会注意到db.copyDatabase()无法工作,因为您的用户需要很多权限,您可能不想给它。以下是手动复制数据库的脚本:

use old_db
db.getCollectionNames().forEach(function(collName) {
    db[collName].find().forEach(function(d){
        db.getSiblingDB('new_db')[collName].insert(d); 
    }) 
});

1
db.copyDatabase 在 MongoDB 4.4 中已经不再使用。 - Dee
我认为这不会复制索引。 - Aaron Silverman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接