Comment renommer une base de données MongoDB?


484

Il y a une faute de frappe dans le nom de ma base de données MongoDB et je cherche à renommer la base de données.

Je peux copier et supprimer comme ça ...

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

Existe-t-il une commande pour renommer une base de données?


de mongo 4.2 even copyDatabaseest également obsolète
Sumit Ramteke

Réponses:


208

Non, il n'y en a pas. Voir https://jira.mongodb.org/browse/SERVER-701

Malheureusement, ce n'est pas une fonctionnalité simple à mettre en œuvre en raison de la façon dont les métadonnées de la base de données sont stockées dans le moteur de stockage d'origine (par défaut). Dans les fichiers MMAPv1, l'espace de noms (par exemple: dbName.collection) qui décrit chaque collection et chaque index inclut le nom de la base de données. Ainsi, pour renommer un ensemble de fichiers de base de données, chaque chaîne d'espace de noms doit être réécrite. Cela a un impact:

  • le fichier .ns
  • chaque fichier numéroté unique pour la collection
  • l'espace de noms pour chaque index
  • noms uniques internes de chaque collection et index
  • le contenu de system.namespaces et system.indexes (ou leurs équivalents à l'avenir)
  • d'autres endroits qui me manquent

Il s'agit simplement de renommer une base de données unique dans une instance mongod autonome . Pour les jeux de répliques, ce qui précède devrait être fait sur chaque nœud de réplique, plus sur chaque nœud chaque entrée d'oplog unique qui fait référence à cette base de données devrait être en quelque sorte invalidée ou réécrite, puis s'il s'agit d'un cluster fragmenté, il faut également ajouter ces les modifications apportées à chaque fragment si la base de données est fragmentée, plus les serveurs de configuration ont toutes les métadonnées de fragment en termes d'espaces de noms avec leurs noms complets.

Il n'y aurait absolument aucun moyen de le faire sur un système en direct.

Pour le faire hors ligne, il faudrait réécrire chaque fichier de base de données pour prendre en compte le nouveau nom, et à ce stade, ce serait aussi lent que la commande "copydb" actuelle ...


4
Ce ticket est ouvert depuis très longtemps. J'ai ajouté mon vote peu important à la liste déjà longue.
DJ van Wyk

4
La façon dont ils ont construit la base de données et l'ont expliqué, renommer semble impossible - pourrait prendre une toute nouvelle architecture. On dirait un gros oubli mais tout est juste en amour, en guerre et en développement logiciel.
serraosays

Donc MongoDB devrait avoir une commande qui appelle deux fonctions, copier et déposer? Je ne vois pas de grande raison d'avoir cette seule commande. Mais cela pourrait être agréable pour certains.
TamusJRoyce

Lorsque vous nommez la base de données pour commencer, cela DEVRAIT simplement être un alias pour un nom interne que Mongo génère (en utilisant une convention de dénomination unique au monde). De cette façon, la modification du nom d'une base de données est aussi simple que la modification de cet alias et sa propagation à tous les nœuds du cluster. Je dis DEVRAIT. Ce n'est pas le cas.
Lonnie Best

396

Vous pouvez faire ceci:

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

Note éditoriale: il s'agit de la même approche que celle utilisée dans la question elle-même, mais elle s'est révélée utile à d'autres malgré tout.


38
Le troisième argument peut en fait être omis, et il sera par défaut sur le même serveur.
Haakon

15
Notez que cela ne fonctionne pas lorsque db_to_rename et db_renamed ne diffèrent qu'en cas de différence. Vous devez utiliser une base de données temporaire dans cette situation. (Je suis juste tombé sur ça :)
Sebastiaan M

71
En quoi est-ce différent de la solution fournie par le PO?
Salvador Dali

5
c'est la même que la question réelle avec la seule différence étant le troisième argument de la copyDatabaseméthode
Gurbakhshish Singh

2
c'est la même que la vraie question avec la seule différence étant le troisième argument de la copyDatabaseméthode *, qui est inutile, et donc une pire solution que celle que le PO connaissait déjà. * cc @GurbakhshishSingh
Trindaz

164

Solution alternative: vous pouvez vider votre base de données et la restaurer sous un nom différent. Comme je l'ai vécu, c'est beaucoup plus rapide que 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
C'est plus rapide et comme "effet secondaire", votre base de données est également compactée.
Comtaler

C'est bien! J'en avais déjà un mongodumpcréé. Je ne savais pas que vous pouvez le restaurer avec un nom différent. Merci!
Dushyant Bangal

5
REMARQUE: cela ne fonctionne pas si vous utilisez --gzipet créez une archive
Dushyant Bangal

9
C'est la voie recommandée maintenant, car elle db.copyDatabase()est désormais obsolète
osolmaz

Notant que non, l' argument --db( -d) est lui-même également obsolète. Il y a eu un peu de parti de dépréciation en cours, semble-t-il, étant donné qu'il a copyDatabaseégalement disparu. J'ai poussé SERVER-701 avec mes notes .
amcgregor

28

REMARQUE: nous espérons que cela a changé dans la dernière version.

Vous ne pouvez pas copier de données entre une instance de mongod MongoDB 4.0 (quelle que soit la valeur FCV) et une instance de mongod MongoDB 3.4 et versions antérieures. https://docs.mongodb.com/v4.0/reference/method/db.copyDatabase/

ALERTE : Hé les gens, faites juste attention lors de la copie de la base de données, si vous ne voulez pas gâcher les différentes collections sous une seule base de données.

Ce qui suit vous montre comment renommer

> show dbs;
testing
games
movies

Pour renommer vous utilisez la syntaxe suivante

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

Exemple:

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

Vous pouvez maintenant supprimer en toute sécurité l'ancienne base de données de la manière suivante

use testing;

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

Maintenant, pensez à ce qui se passe si vous essayez de renommer le nouveau nom de la base de données avec le nom de la base de données existante

Exemple:

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

Ainsi, dans ce contexte, toutes les collections (tables) de tests seront copiées dans la base de données des films .



@amcgregor merci de nous en informer. J'ai ajouté un commentaire pour le même. J'espère que cela aide quelqu'un.
Channaveer Hakari

8

Bien que Mongodb ne fournisse pas la commande rename Database, il fournit la commande r ename Collection , qui non seulement modifie le nom de la collection, mais aussi le nom de la base de données.

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

Cette commande ne fait que modifier les métadonnées, le coût est très faible, il suffit de parcourir toutes les collections sous db1, renommé db2pour obtenir renommer le nom de la base de données.
vous pouvez le faire dans ce script 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});
}

qu'en est-il des index et autres métadonnées sont-ils conservés ou perdus?
Udit Bhardwaj

@UDB Très probablement conservé. "Renommer une collection" est une transformation d'espace de noms , essentiellement votre collection nommée foodans la barbase de données a un espace de noms de bar.foo. L'index sur a _iddonc l'espace de noms bar.foo._id_. Renommant la collection (devrait) effectuer une recherche de préfixe et remplacer tous les espaces de noms , il est au courant, similaire au --nsFromet --nsTo optionsmongorestore .
amcgregor

1
Le coût peut être ÉNORME! docs.mongodb.com/manual/reference/command/renameCollection/… Si la base de données cible est la même que la base de données source, renameCollection change simplement l'espace de noms. Ceci est une opération rapide. Si la base de données cible diffère de la base de données source, renameCollection copie tous les documents de la collection source vers la collection cible. Selon la taille de la collection, cela peut prendre plus de temps.
nagylzs

Veuillez modifier votre réponse. Votre réponse est utile, car il est possible de déplacer une collection vers une autre base de données avec cette commande. Mais c'est incorrect et cela peut induire les autres en erreur.
nagylzs

6

Le processus ci-dessus est lent, vous pouvez utiliser la méthode ci-dessous mais vous devez déplacer collection par collection vers une autre base de données.

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

Excellente suggestion à mon humble avis. Cependant, il convient de noter que cela ne libérera pas de l'espace de la base de données d'origine, mais le changement de nom devrait être beaucoup plus rapide que la copie des données.
sirfz

1
Grattez cela, il fait quand même une copie (car il ne supprime pas l'espace, ce n'est pas vraiment un simple renommage) donc il n'y a pas de réel avantage à cette méthode par rapport au copier-déposer.
sirfz

5

Il n'existe aucun mécanisme pour renommer les bases de données. La réponse actuellement acceptée au moment de la rédaction est factuellement correcte et offre quelques détails de fond intéressants quant à l'excuse en amont, mais n'offre aucune suggestion pour reproduire le comportement. D'autres réponses pointent vers copyDatabase, ce qui n'est plus une option car la fonctionnalité a été supprimée dans 4.0 . J'ai mis à jour le SERVER-701 avec mes notes et mon incrédulité. 🙃

Un comportement équivalent implique mongodumpet mongorestoredans un peu de danse:

  1. Exportez vos données en prenant note des "espaces de noms" utilisés. Par exemple, sur l'un de mes ensembles de données, j'ai une collection avec l'espace de noms byzmcbehoomrfjcs9vlj.Analytics- ce préfixe (en fait le nom de la base de données ) sera nécessaire à l'étape suivante.

  2. Importez vos données, vos fournitures --nsFromet vos --nsToarguments. ( Documentation. ) Poursuivant mon exemple hypothétique (et extrêmement illisible) ci-dessus, pour restaurer un nom plus sensé, j'invoque:

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

Certains peuvent également pointer l' --dbargument de mongorestore, mais cela aussi est obsolète et déclenche un avertissement contre l'utilisation sur les sauvegardes de dossiers non BSON avec une suggestion complètement erronée de " use --nsInclude instead". La traduction de l'espace de noms ci-dessus équivaut à l'utilisation de l' --dboption et est la configuration de manipulation d'espace de noms correcte à utiliser car nous n'essayons pas de filtrer ce qui est en cours de restauration.


1
--nsFromet a --nsTotravaillé pour moi. Je vous remercie!
Bhargav Shah

mongodump avec nsFrom / To est la réponse officielle à partir de 2020
PaoloC

4

J'ai essayé de faire.

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

et a appris qu'il a été déprécié par la communauté mongo bien qu'il ait créé la sauvegarde ou renommé DB.

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
}

Donc, pas convaincu de l'approche ci-dessus, j'ai dû prendre Dump of local en utilisant la commande ci-dessous

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

connecté à Db.

use DB_TobeRenamed

puis

db.dropDatabase()

puis restauré la base de données avec la commande.

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

2

Dans le cas où vous placez toutes vos données dans la base de données d'administration (vous ne devriez pas), vous remarquerez que db.copyDatabase()cela ne fonctionnera pas car votre utilisateur nécessite de nombreux privilèges que vous ne voulez probablement pas lui donner. Voici un script pour copier la base de données manuellement:

use old_db
db.getCollectionNames().forEach(function(collName) {
    db[collName].find().forEach(function(d){
        db.getSiblingDB('new_db')[collName].insert(d); 
    }) 
});
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.