Come si rinomina un database MongoDB?


484

C'è un errore di battitura nel mio nome di database MongoDB e sto cercando di rinominare il database.

Posso copiare ed eliminare in questo modo ...

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

Esiste un comando per rinominare un database?


dal mongo 4.2 anche copyDatabaseè deprecato
Sumit Ramteke,

Risposte:


208

No non c'è. Vedi https://jira.mongodb.org/browse/SERVER-701

Sfortunatamente, questa non è una funzionalità semplice da implementare a causa del modo in cui i metadati del database sono archiviati nel motore di archiviazione originale (predefinito). Nei file MMAPv1, lo spazio dei nomi (ad es. DbName.collection) che descrive ogni singola raccolta e indice include il nome del database, quindi per rinominare un set di file di database, ogni singola stringa dello spazio dei nomi dovrebbe essere riscritta. Questo ha un impatto:

  • il file .ns
  • ogni singolo file numerato per la raccolta
  • lo spazio dei nomi per ogni indice
  • nomi univoci interni di ogni raccolta e indice
  • contenuto di system.namespaces e system.indexes (o loro equivalenti in futuro)
  • altre posizioni che potrebbero mancare

Questo serve solo per realizzare una ridenominazione di un singolo database in un'istanza mongod autonoma . Per i set di repliche, quanto sopra dovrebbe essere fatto su ogni nodo di replica, più su ogni nodo ogni singola voce di oplog che fa riferimento a questo database dovrebbe essere in qualche modo invalidata o riscritta, e quindi se si tratta di un cluster frammentato, è necessario aggiungere anche questi cambia in ogni frammento se il DB è frammentato, inoltre i server di configurazione hanno tutti i metadati del frammento in termini di spazi dei nomi con i loro nomi completi.

Non ci sarebbe assolutamente modo di farlo su un sistema live.

Per farlo offline, richiederebbe riscrivere ogni singolo file di database per adattarlo al nuovo nome, e a quel punto sarebbe lento quanto l'attuale comando "copydb" ...


4
Quel biglietto è stato aperto per molto tempo. Ho aggiunto il mio voto poco importante alla già lunga lista.
DJ van Wyk,

4
Il modo in cui hanno costruito il DB e lo hanno spiegato, la ridenominazione sembra impossibile - potrebbe richiedere un'architettura completamente nuova. Sembra una grande svista, ma tutto è corretto in amore, guerra e sviluppo software.
serraosays,

Quindi MongoDB dovrebbe avere un comando che chiama due funzioni, copia e rilascia? Non vedo un grande motivo per avere questo singolo comando. Ma potrebbe essere carino per alcuni.
TamusJRoyce,

Quando si nomina il database per cominciare, DOVREBBE essere solo un alias per un nome interno che Mongo genera (usando una convenzione di denominazione univoca a livello globale). In questo modo, cambiare il nome di un database è semplice come cambiare quell'alias e propagarlo a tutti i nodi del cluster. Dico DOVREBBE. Questo non è il caso.
Lonnie Best

396

Potresti farlo:

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

Nota editoriale: questo è lo stesso approccio usato nella domanda stessa ma si è dimostrato utile per gli altri a prescindere.


38
Il terzo argomento può effettivamente essere omesso e verrà impostato automaticamente sullo stesso server.
Haakon,

15
Si noti che questo non funziona quando db_to_rename e db_renamed differiscono solo nel caso. Devi usare un database temporaneo in quella situazione. (Mi sono appena imbattuto in questo :)
Sebastiaan M

71
In che modo differisce dalla soluzione fornita dal PO?
Salvador Dali,

5
questa è la stessa domanda reale, con l'unica differenza che è il terzo argomento del copyDatabasemetodo
Gurbakhshish Singh,

2
questa è la stessa domanda effettiva, con l'unica differenza che è il terzo argomento del copyDatabasemetodo *, che non è necessario, e quindi una soluzione peggiore di quella di cui l'OP era già a conoscenza. * cc @GurbakhshishSingh
Trindaz

164

Soluzione alternativa: puoi scaricare il tuo db e ripristinarlo con un nome diverso. Come ho sperimentato, è molto più veloce di 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
Questo è più veloce e come "effetto collaterale", anche il tuo database è compatto.
Comtaler,

Questo è fantastico! Ne avevo già mongodumpcreato uno . Non sapevo che puoi ripristinarlo con un nome diverso. Grazie!
Dushyant Bangal,

5
NOTA: Questo non funziona se si utilizza --gzipe si crea un archivio
Dushyant Bangal

9
Questo è il modo raccomandato ora, poiché db.copyDatabase()ora è deprecato
osolmaz,

Notando che no, anche l' argomento --db( -d) è deprecato. Sembra che stia succedendo un po 'di deprecazioni, dato che copyDatabaseanche se ne è andato. Ho colpito SERVER-701 con i miei appunti .
amcgregor,

28

NOTA: si spera che questo sia cambiato nell'ultima versione.

Non è possibile copiare dati tra un'istanza mongod MongoDB 4.0 (indipendentemente dal valore FCV) e un'istanza mongod MongoDB 3.4 e precedente. https://docs.mongodb.com/v4.0/reference/method/db.copyDatabase/

AVVISO : Hey gente state solo attenti mentre copiate il database, se non volete rovinare le diverse raccolte in un unico database.

Quanto segue mostra come rinominare

> show dbs;
testing
games
movies

Per rinominare si utilizza la sintassi seguente

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

Esempio:

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

Ora puoi eliminare in sicurezza il vecchio db nel modo seguente

use testing;

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

Ora pensa cosa succede se provi a rinominare il nuovo nome del database con il nome del database esistente

Esempio:

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

Quindi in questo contesto tutte le raccolte (tabelle) di test verranno copiate nel database dei film .



@amcgregor grazie per la notifica. Ho aggiunto un commento per lo stesso. Spero che aiuti qualcuno.
Channaveer Hakari,

8

Sebbene Mongodb non fornisca il comando rinomina Database, fornisce il comando r ename Collection , che non solo modifica il nome della raccolta, ma modifica anche il nome del database.

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

Questo comando modifica solo i metadati, il costo è molto piccolo, dobbiamo solo attraversare tutte le raccolte sotto db1, rinominate db2per ottenere il nome del database.
puoi farlo in questo 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});
}

che dire di indici e altri metadati vengono mantenuti o persi?
Udit Bhardwaj,

@UDB Molto probabilmente conservato. "Rinominare una raccolta" è una trasformazione dello spazio dei nomi , essenzialmente la raccolta denominata fooall'interno del bardatabase ha uno spazio dei nomi di bar.foo. L'indice su _idha quindi lo spazio dei nomi bar.foo._id_. Rinominare la raccolta (dovrebbe) eseguire una ricerca prefisso e sostituirla su tutti gli spazi dei nomi di cui è a conoscenza, in modo simile alle opzioni--nsFrom e . --nsTo mongorestore
amcgregor,

1
Il costo può essere ENORME! docs.mongodb.com/manual/reference/command/renameCollection/… Se il database di destinazione è uguale al database di origine, renameCollection cambia semplicemente lo spazio dei nomi. Questa è un'operazione rapida. Se il database di destinazione differisce dal database di origine, renameCollection copia tutti i documenti dalla raccolta di origine nella raccolta di destinazione. A seconda delle dimensioni della raccolta, il completamento potrebbe richiedere più tempo.
nagylzs

Per favore cambia la tua risposta. La tua risposta è utile, perché è possibile spostare una raccolta in un altro database con questo comando. Ma non è corretto e può fuorviare gli altri.
nagylzs

6

Il processo sopra descritto è lento, è possibile utilizzare il metodo seguente ma è necessario spostare la raccolta per raccolta su un altro db.

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

Ottimo suggerimento IMHO. Tuttavia, vale la pena notare che questo non libererà lo spazio dal DB originale ma la ridenominazione dovrebbe essere molto più veloce della copia dei dati.
sirfz,

1
Scratch it, fa comunque una copia (dal momento che non rimuove lo spazio, non è in realtà un semplice rinominare) quindi non c'è alcun vantaggio reale con questo metodo rispetto al copia e rilascia.
sirfz,

5

Non esiste alcun meccanismo per rinominare i database. La risposta attualmente accettata al momento della stesura è di fatto corretta e offre alcuni interessanti dettagli di base sulla scusa a monte, ma non offre suggerimenti per replicare il comportamento. Altre risposte indicano copyDatabaseche non è più un'opzione poiché la funzionalità è stata rimossa in 4.0 . Ho aggiornato SERVER-701 con le mie note e incredulità. 🙃

Comportamento equivalente coinvolge mongodumpe mongorestorein un po 'di danza:

  1. Esporta i tuoi dati, prendendo nota degli "spazi dei nomi" in uso. Ad esempio, su uno dei miei set di dati, ho una raccolta con lo spazio dei nomi byzmcbehoomrfjcs9vlj.Analytics- quel prefisso (in realtà il nome del database ) sarà necessario nel passaggio successivo.

  2. Importa i tuoi dati, informazioni --nsFrome --nsToargomenti. ( Documentazione. ) Continuando con il mio esempio ipotetico (ed estremamente illeggibile) di cui sopra, per ripristinare un nome più sensato, invoco:

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

Alcuni potrebbero anche puntare --dball'argomento mongorestore, tuttavia anche questo è deprecato e innesca un avvertimento contro l'uso su backup di cartelle non BSON con un suggerimento completamente errato a " use --nsInclude instead". La traduzione dello spazio dei nomi sopra è equivalente all'uso --dbdell'opzione ed è la corretta configurazione di manipolazione dello spazio dei nomi da usare poiché non stiamo tentando di filtrare ciò che viene ripristinato.


1
--nsFrome ha --nsTolavorato per me. Grazie!
Bhargav Shah

mongodump con nsFrom / To è la risposta ufficiale a partire dal 2020
PaoloC

4

Ho provato a farlo.

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

e ho scoperto che è stato deprecato dalla comunità mongo sebbene abbia creato il backup o rinominato 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
}

Quindi non convinto con l'approccio sopra ho dovuto prendere Dump del locale usando il comando sottostante

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

collegato a Db.

use DB_TobeRenamed

poi

db.dropDatabase()

quindi ripristinato il DB con comando.

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

2

Nel caso in cui metti tutti i tuoi dati nel database di amministrazione (non dovresti), noterai db.copyDatabase()che non funzionerà perché il tuo utente richiede molti privilegi che probabilmente non vorrai concederli. Ecco uno script per copiare manualmente il database:

use old_db
db.getCollectionNames().forEach(function(collName) {
    db[collName].find().forEach(function(d){
        db.getSiblingDB('new_db')[collName].insert(d); 
    }) 
});
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.