Wie benennt man eine MongoDB-Datenbank um?

484

Mein MongoDB-Datenbankname enthält einen Tippfehler und ich möchte die Datenbank umbenennen.

Ich kann so kopieren und löschen ...

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

Gibt es einen Befehl zum Umbenennen einer Datenbank?

Brian Hempel
quelle
von Mongo 4.2 selbst copyDatabaseist ebenfalls veraltet
Sumit Ramteke

Antworten:

208

Nein, gibt es nicht. Siehe https://jira.mongodb.org/browse/SERVER-701

Leider ist dies für uns keine einfache Funktion, da Datenbankmetadaten in der ursprünglichen (Standard-) Speicher-Engine gespeichert sind. In MMAPv1-Dateien enthält der Namespace (z. B. dbName.collection), der jede einzelne Sammlung und jeden einzelnen Index beschreibt, den Datenbanknamen. Um also eine Reihe von Datenbankdateien umzubenennen, muss jede einzelne Namespace-Zeichenfolge neu geschrieben werden. Dies wirkt sich aus:

  • die .ns-Datei
  • jede einzelne nummerierte Datei für die Sammlung
  • der Namespace für jeden Index
  • interne eindeutige Namen jeder Sammlung und jedes Index
  • Inhalt von system.namespaces und system.indexes (oder deren Entsprechungen in der Zukunft)
  • andere Orte, die ich möglicherweise vermisse

Dies dient nur dazu, eine einzelne Datenbank in einer eigenständigen Mongod-Instanz umzubenennen. Für Replikatsätze müsste das oben Genannte auf jedem Replikatknoten durchgeführt werden, und auf jedem Knoten müsste jeder einzelne Oplog-Eintrag, der auf diese Datenbank verweist, irgendwie ungültig gemacht oder neu geschrieben werden. Wenn es sich dann um einen Sharded-Cluster handelt, müssen diese ebenfalls hinzugefügt werden ändert sich zu jedem Shard, wenn die Datenbank sharded ist, und die Konfigurationsserver verfügen über alle Shard-Metadaten in Form von Namespaces mit ihren vollständigen Namen.

Auf einem Live-System gibt es absolut keine Möglichkeit, dies zu tun.

Um es offline zu machen, müsste jede einzelne Datenbankdatei neu geschrieben werden, um den neuen Namen aufzunehmen, und zu diesem Zeitpunkt wäre es so langsam wie der aktuelle Befehl "copydb" ...

pingw33n
quelle
4
Dieses Ticket ist schon sehr lange geöffnet. Ich habe meine weniger wichtige Stimme zur bereits langen Liste hinzugefügt.
DJ van Wyk
4
Die Art und Weise, wie sie die Datenbank erstellt und erklärt haben, scheint unmöglich umzubenennen - könnte eine völlig neue Architektur erfordern. Scheint ein großes Versehen zu sein, aber in Bezug auf Liebe, Krieg und Softwareentwicklung ist alles fair.
Serraosays
MongoDB sollte also einen Befehl haben, der zwei Funktionen aufruft: Kopieren und Löschen? Ich sehe keinen großen Grund, diesen einzigen Befehl zu haben. Aber für manche könnte es schön sein.
TamusJRoyce
Wenn Sie die Datenbank zunächst benennen, sollte dies nur ein Alias ​​für einen internen Namen sein, den Mongo generiert (unter Verwendung einer global eindeutigen Namenskonvention). Auf diese Weise ist das Ändern des Datenbanknamens so einfach wie das Ändern dieses Alias ​​und das Weitergeben an alle Knoten im Cluster. Ich sage sollte. Das ist nicht der Fall.
Lonnie Best
396

Sie könnten dies tun:

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

Anmerkung der Redaktion: Dies ist der gleiche Ansatz, der in der Frage selbst verwendet wird, hat sich jedoch für andere als nützlich erwiesen.

bzmw
quelle
38
Das dritte Argument kann tatsächlich weggelassen werden und wird standardmäßig auf demselben Server verwendet.
Haakon
15
Beachten Sie, dass dies nicht funktioniert, wenn sich db_to_rename und db_renamed nur für den Fall unterscheiden. In dieser Situation müssen Sie eine temporäre Datenbank verwenden. (Ich bin gerade darauf gestoßen :)
Sebastiaan M
71
Wie unterscheidet sich dies von der vom OP bereitgestellten Lösung?
Salvador Dali
5
Dies ist das gleiche wie die eigentliche Frage, mit dem einzigen Unterschied, dass es sich um das dritte Argument in der copyDatabaseMethode handelt
Gurbakhshish Singh,
2
Dies ist das Gleiche wie die eigentliche Frage, mit dem einzigen Unterschied, dass das dritte Argument in copyDatabaseMethode * unnötig ist und daher eine schlechtere Lösung darstellt, die dem OP bereits bekannt war. * cc @GurbakhshishSingh
Trindaz
164

Alternative Lösung: Sie können Ihre Datenbank sichern und unter einem anderen Namen wiederherstellen. Wie ich erlebt habe, ist es viel schneller als 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/

Tomako
quelle
6
Dies ist schneller und als "Nebeneffekt" wird auch Ihre Datenbank komprimiert.
Comtaler
Das ist toll! Ich hatte schon eine mongodumperstellt. Wusste nicht, dass Sie es unter einem anderen Namen wiederherstellen können. Vielen Dank!
Dushyant Bangal
5
HINWEIS: Dies funktioniert nicht, wenn Sie --gzipein Archiv verwenden und erstellen
Dushyant Bangal
9
Dies ist jetzt der empfohlene Weg, da er db.copyDatabase()jetzt veraltet ist
Osolmaz
Mit der Bemerkung, dass nein, das Argument --db( -d) selbst ebenfalls veraltet ist. Es hat anscheinend eine Art Abwertungsparty stattgefunden, vorausgesetzt, sie copyDatabaseist auch weg. Ich habe SERVER-701 mit meinen Notizen angestochert .
Amcgregor
28

HINWEIS: Hoffentlich hat sich dies in der neuesten Version geändert.

Sie können keine Daten zwischen einer MongoDB 4.0-Mongod-Instanz (unabhängig vom FCV-Wert) und einer MongoDB 3.4- und einer früheren Mongod-Instanz kopieren. https://docs.mongodb.com/v4.0/reference/method/db.copyDatabase/

ALERT : Hey Leute, seid beim Kopieren der Datenbank nur vorsichtig, wenn ihr die verschiedenen Sammlungen unter einer einzigen Datenbank nicht durcheinander bringen wollt.

Im Folgenden erfahren Sie, wie Sie umbenennen

> show dbs;
testing
games
movies

Zum Umbenennen verwenden Sie die folgende Syntax

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

Beispiel:

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

Jetzt können Sie die alte Datenbank auf folgende Weise sicher löschen

use testing;

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

Stellen Sie sich nun vor, was passiert, wenn Sie versuchen, den neuen Datenbanknamen in den vorhandenen Datenbanknamen umzubenennen

Beispiel:

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

So ist in diesem Zusammenhang alle Sammlungen (Tabellen) der Tests werden kopiert Filme Datenbank.

Channaveer Hakari
quelle
@amcgregor danke für die Benachrichtigung. Ich habe einen Kommentar dazu hinzugefügt. Hoffe es hilft jemandem.
Channaveer Hakari
8

Obwohl Mongodb den Befehl "Datenbank umbenennen" nicht bereitstellt, stellt es den Befehl "Sammlung umbenennen" bereit , mit dem nicht nur der Sammlungsname, sondern auch der Datenbankname geändert wird .

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

Dieser Befehl ändert nur die Metadaten, die Kosten sind sehr gering. Wir müssen nur alle Sammlungen durchlaufen db1, die umbenannt wurden db2, um den Namen der Datenbank umzubenennen.
Sie können es in diesem Js-Skript tun

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});
}
HbnKing
quelle
Was ist mit Indizes und anderen Metadaten, die gepflegt werden oder verloren gehen?
Udit Bhardwaj
@UDB Sehr wahrscheinlich erhalten. "Umbenennen einer Sammlung" ist eine Namespace-Umwandlung . Im Wesentlichen hat Ihre fooin der barDatenbank genannte Sammlung einen Namespace von bar.foo. Der Index auf _idhat also den Namespace bar.foo._id_. Durch das Umbenennen der Sammlung (sollte) eine Präfixsuche und -ersetzung für alle ihm bekannten Namespaces durchgeführt werden, ähnlich wie bei --nsFromund --nsTo Optionen fürmongorestore .
Amcgregor
1
Die Kosten können riesig sein! docs.mongodb.com/manual/reference/command/renameCollection/… Wenn die Zieldatenbank mit der Quellendatenbank identisch ist, ändert renameCollection einfach den Namespace. Dies ist eine schnelle Operation. Wenn sich die Zieldatenbank von der Quellendatenbank unterscheidet, kopiert renameCollection alle Dokumente aus der Quellensammlung in die Zielsammlung. Abhängig von der Größe der Sammlung kann dies länger dauern.
Nagylzs
Bitte ändern Sie Ihre Antwort. Ihre Antwort ist hilfreich, da mit diesem Befehl eine Sammlung in eine andere Datenbank verschoben werden kann. Aber es ist falsch und kann andere irreführen.
Nagylzs
6

Der obige Vorgang ist langsam. Sie können die folgende Methode verwenden, müssen jedoch Sammlung für Sammlung in eine andere Datenbank verschieben.

use admin
db.runCommand({renameCollection: "[db_old_name].[collection_name]", to: "[db_new_name].[collection_name]"})
Madan Ram
quelle
Hervorragender Vorschlag IMHO. Es ist jedoch anzumerken, dass dies nicht den Speicherplatz aus der ursprünglichen Datenbank freigibt, sondern dass das Umbenennen viel schneller sein sollte als das Kopieren der Daten.
Sirfz
1
Scratch that, es macht sowieso eine Kopie (da es den Speicherplatz nicht entfernt, ist es nicht wirklich eine einfache Umbenennung), so dass diese Methode keinen wirklichen Vorteil gegenüber Kopieren und Löschen hat.
Sirfz
5

Es gibt keinen Mechanismus zum Umbenennen von Datenbanken. Die zum Zeitpunkt des Schreibens derzeit akzeptierte Antwort ist sachlich korrekt und bietet einige interessante Hintergrundinformationen zur vorgelagerten Entschuldigung, bietet jedoch keine Vorschläge zur Replikation des Verhaltens. Andere Antworten zeigen auf copyDatabase, was keine Option mehr ist, da die Funktionalität in 4.0 entfernt wurde . Ich habe SERVER-701 mit meinen Notizen und Ungläubigkeit aktualisiert . 🙃

Gleichwertiges Verhalten beinhaltet mongodumpund mongorestorein einem kleinen Tanz:

  1. Exportieren Sie Ihre Daten und notieren Sie sich die verwendeten "Namespaces". In einem meiner Datasets habe ich beispielsweise eine Sammlung mit dem Namespace byzmcbehoomrfjcs9vlj.Analytics- dieses Präfix ( eigentlich der Datenbankname ) wird im nächsten Schritt benötigt.

  2. Importieren Sie Ihre Daten, Lieferungen --nsFromund --nsToArgumente. ( Dokumentation. ) Wenn ich mit meinem obigen hypothetischen (und äußerst unlesbaren) Beispiel fortfahre, um einen sinnlicheren Namen wiederherzustellen, rufe ich Folgendes auf:

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

Einige mögen auch auf das --dbArgument zu mongorestore verweisen, aber auch dies ist veraltet und löst eine Warnung vor der Verwendung bei Nicht-BSON-Ordnersicherungen mit einem völlig fehlerhaften Vorschlag an " use --nsInclude instead" aus. Die obige Namespace-Übersetzung entspricht der Verwendung der --dbOption und ist das richtige Setup für die Namespace-Manipulation, da wir nicht versuchen, zu filtern, was wiederhergestellt wird.

amcgregor
quelle
1
--nsFromund --nsToarbeitete für mich. Vielen Dank!
Bhargav Shah
mongodump mit nsFrom / To sind die offizielle Antwort ab 2020
PaoloC
4

Ich habe es versucht.

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

und erfuhr, dass es von der Mongo-Community veraltet ist, obwohl es das Backup erstellt oder die Datenbank umbenannt hat.

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
}

Also nicht überzeugt von dem obigen Ansatz, musste ich Dump of local mit dem folgenden Befehl nehmen

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

verbunden mit Db.

use DB_TobeRenamed

dann

db.dropDatabase()

Stellen Sie dann die Datenbank mit dem Befehl wieder her.

mongorestore -host hostName -d Db_NewName E://FileName/
Abhishek Kumar
quelle
2

Wenn Sie alle Ihre Daten in die Admin-Datenbank stellen (sollten Sie nicht), werden Sie feststellen, db.copyDatabase()dass dies nicht funktioniert, da Ihr Benutzer viele Berechtigungen benötigt, die Sie wahrscheinlich nicht vergeben möchten. Hier ist ein Skript zum manuellen Kopieren der Datenbank:

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