您如何重命名MongoDB数据库?


483

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

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

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

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


mongo 4.2甚至copyDatabase已弃用
Sumit Ramteke

Answers:


208

不,没有。参见https://jira.mongodb.org/browse/SERVER-701

不幸的是,由于数据库元数据存储在原始(默认)存储引擎中的方式,这对我们来说不是一个简单的功能。在MMAPv1文件中,描述每个单个集合和索引的名称空间(例如:dbName.collection)都包含数据库名称,因此要重命名一组数据库文件,则必须重写每个名称空间字符串。这会影响:

  • .ns文件
  • 集合的每个编号文件
  • 每个索引的名称空间
  • 每个集合和索引的内部唯一名称
  • system.namespaces和system.indexes的内容(或将来的等效内容)
  • 我可能想念的其他地方

这仅仅是为了在独立 mongod实例中完成单个数据库的重命名。对于副本集,需要在每个副本节点上执行上述操作,此外,在每个节点上,必须以某种方式使引用此数据库的每个操作日志条目无效或重写,然后,如果它是分片群集,则还需要添加这些如果分片了数据库,则对每个分片进行更改,另外,配置服务器具有所有具有名称全名的分片元数据。

绝对不可能在实时系统上执行此操作。

要离线执行此操作,将需要重新写入每个数据库文件以容纳新名称,这时它将和当前的“ copydb”命令一样慢...


4
那张票已经开放很长时间了。我已将不重要的投票添加到已经很长的列表中。
DJ van Wyk 2014年

4
他们建立数据库并解释数据库的方式,重命名似乎是不可能的-可能需要全新的架构。似乎是一个很大的疏忽,但是在爱情,战争和软件开发方面,一切都是公平的。
serraosays

那么MongoDB应该有一个调用两个函数(复制和删除)的命令?我认为使用此单个命令的理由不大。但这对某些人可能很好。
TamusJRoyce '17

当您命名数据库开始时,该名称应该只是Mongo生成的内部名称的别名(使用全局唯一的命名约定)。这样,更改数据库的名称就像更改该别名并将其传播到集群中的所有节点一样简单。我说应该。不是这种情况。
Lonnie Best,

396

您可以这样做:

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

编者注:这与问题本身使用的方法相同,但无论如何对其他人都有用。


38
实际上可以省略第3个参数,它将默认使用同一服务器。
哈孔

15
请注意,当db_to_rename和db_renamed仅大小写不同时,此方法不起作用。在这种情况下,您必须使用一个临时数据库。(我刚遇到这个问题:)
塞巴斯蒂安M

71
这与OP提供的解决方案有何不同?
Salvador Dali

5
这与实际问题相同,唯一的不同是copyDatabase方法中的第三个论点
Gurbakhshish Singh

2
这与实际问题相同,唯一的区别是copyDatabase方法*中的第三个参数,这是不必要的,因此是OP已经意识到的一个更差的解决方案。* cc @GurbakhshishSingh
Trindaz

164

替代解决方案:您可以转储数据库并以其他名称还原它。根据我的经验,它比快得多db.copyDatabase()

$ mongodump -d old_db_name -o mongodump/
$ mongorestore -d new_db_name mongodump/old_db_name

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


6
这样速度更快,并且作为“副作用”,您的数据库也被压缩。
Comtaler '16

这很棒!我已经mongodump创建了。不知道您可以使用其他名称还原它。谢谢!
Dushyant Bangal,2017年

5
注意:如果您使用--gzip和创建档案文件,则无法使用
Dushyant Bangal,2017年

9
这是现在推荐的方法,因为db.copyDatabase()现在已弃用
osolmaz

注意,--db-d)参数本身也已被弃用。似乎已经有过一个弃权聚会,鉴于copyDatabase也已经消失了。 我用笔记戳了SERVER-701
amcgregor

28

注意:希望这已在最新版本中更改。

您不能在MongoDB 4.0 mongod实例(无论FCV值如何)与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'); 

因此,在这种情况下,所有测试集(表)都将复制到电影数据库。



@amcgregor感谢您的通知。我添加了相同的评论。希望它能帮助一些人。
Channaveer Hakari

8

尽管Mongodb不提供重命名数据库命令,但它提供了r ename Collection命令,它不仅可以修改集合名称,还可以修改数据库名称。

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});
}

索引或其他元数据会被维护还是丢失?
Udit Bhardwaj

@UDB很可能保留了。“重命名集合”是名称空间的转换,实质上foo,在bar数据库中命名的集合的名称空间为bar.foo。索引_id因此具有名称空间bar.foo._id_。重命名集合(应)以执行前缀搜索并在它知道的所有名称空间上进行替换,类似于的--nsFrom--nsTo 选项mongorestore
amcgregor

1
费用可能是巨大的!docs.mongodb.com/manual/reference/command/renameCollection/…如果目标数据库与源数据库相同,则renameCollection只会更改名称空间。这是一个快速的操作。如果目标数据库与源数据库不同,则renameCollection将所有文档从源集合复制到目标集合。根据集合的大小,这可能需要更长的时间才能完成。
nagylzs

请更改您的答案。您的答案很有帮助,因为可以使用此命令将集合移至另一个数据库。但这是不正确的,并且可能会误导他人。
nagylzs

6

上面的过程很慢,您可以使用下面的方法,但是您需要将每个集合移到另一个数据库。

use admin
db.runCommand({renameCollection: "[db_old_name].[collection_name]", to: "[db_new_name].[collection_name]"})

很棒的建议恕我直言。但是,值得注意的是,这不会释放原始数据库的空间,但重命名应该比复制数据快得多。
sirfz 2015年

1
从头开始,它还是会进行复制(因为它不会删除空格,所以它实际上并不是简单的重命名),因此与复制和删除相比,此方法没有真正的优势。
sirfz 2015年

5

没有重命名数据库的机制。将在写作时目前公认的答案是正确的事实,并提供了一些有趣的背景细节为借口上游,但提供了复制的行为没有任何建议。指向其他答案copyDatabase,由于该功能已在4.0中删除,因此不再是选择。我已经用注释和不确定性更新了SERVER-701。🙃

等效行为牵涉其中,mongodumpmongorestore有一点点跳动:

  1. 导出数据,并记下正在使用的“命名空间”。例如,在我的一个数据集上,我有一个带有名称空间的集合byzmcbehoomrfjcs9vlj.Analytics- 下一步将需要该前缀(实际上是数据库名称)。

  2. 导入您的数据,供应--nsFrom--nsTo参数。(文档。)继续我上面的假设(且极其不易理解)的示例,为了恢复为更有意义的名称,我调用:

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

有些人可能还指出了--dbmongorestore 的参数,但是,该参数也已被弃用,并在完全错误地建议“ use --nsInclude instead”的情况下触发警告,禁止在非BSON文件夹备份上使用。上面的名称空间转换等效于使用该--db选项,并且是正确的名称空间操作设置,因为我们没有尝试过滤要还原的内容。


1
--nsFrom--nsTo为我工作。谢谢!
Bhargav Shah

截至2020年,带有nsFrom / To的mongodump是官方答复
PaoloC

4

我试过了

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
}

所以我不相信上面的方法,我不得不使用下面的命令进行本地转储

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

连接到Db。

use DB_TobeRenamed

然后

db.dropDatabase()

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

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

2

如果您将所有数据都放在了管理数据库中(您不应该这样做),您会注意到db.copyDatabase()它将无法工作,因为您的用户需要很多特权,而您可能不想授予这些特权。这是一个手动复制数据库的脚本:

use old_db
db.getCollectionNames().forEach(function(collName) {
    db[collName].find().forEach(function(d){
        db.getSiblingDB('new_db')[collName].insert(d); 
    }) 
});
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.