Come copiare una raccolta da un database all’altro in MongoDB

C’è un modo semplice per fare questo?

Al momento non ci sono comandi in MongoDB che facciano questo. Si prega di notare il biglietto JIRA con relativa richiesta di funzionalità .

Potresti fare qualcosa come:

db..find().forEach(function(d){ db.getSiblingDB('')[''].insert(d); }); 

Si prega di notare che con questo, i due database avrebbero bisogno di condividere lo stesso mongod per farlo funzionare.

Oltre a ciò, è ansible eseguire un mongodump di una raccolta da un database e quindi mongorestore della raccolta sull’altro database.

Il modo migliore è quello di fare un mongodump poi mongorestore.

Puoi selezionare la raccolta tramite:

 mongodump -d some_database -c some_collection 

[Facoltativamente, zip some_database.zip some_database/* -r il dump ( zip some_database.zip some_database/* -r ) e lo scp altrove)

Quindi ripristinalo:

 mongorestore -d some_other_db -c some_or_other_collection dump/some_collection.bson 

I dati esistenti in some_or_other_collection verranno conservati. In questo modo puoi “aggiungere” una collezione da un database all’altro.

Prima della versione 2.4.3, dovrai anche aggiungere i tuoi indici dopo aver copiato i tuoi dati. A partire dalla 2.4.3, questa procedura è automatica e puoi disabilitarla con --noIndexRestore .

In realtà, c’è un comando per spostare una collezione da un database all’altro. Non si chiama “move” o “copy”.

Per copiare una raccolta, puoi clonarla sullo stesso db, quindi spostare il clone.

Per clonare:

 > use db1 > db.source_collection.find().forEach( function(x){db.collection_copy.insert(x)} ); 

Spostare:

 > use admin switched to db admin > db.runCommand({renameCollection: 'db1.source_collection', to: 'db2.target_collection'}) // who'd think rename could move? 

Le altre risposte sono migliori per copiare la raccolta, ma ciò è particolarmente utile se stai cercando di spostarlo.

Vorrei abusare della funzione connect in mongo cli mongo doc . questo significa che puoi iniziare una o più connessioni. se si desidera copiare la raccolta clienti da test a test2 nello stesso server. per prima cosa inizi la shell mongo

 use test var db2 = connect('localhost:27017/test2') 

fare una ricerca normale e copiare i primi 20 record in test2.

 db.customer.find().limit(20).forEach(function(p) { db2.customer.insert(p); }); 

o filtrare secondo alcuni criteri

 db.customer.find({"active": 1}).forEach(function(p) { db2.customer.insert(p); }); 

basta cambiare l’host locale in IP o hostname per connettersi al server remoto. Lo uso per copiare i dati di test in un database di test per il test.

Se tra due istanze remote mongod, utilizzare

 { cloneCollection: "", from: "", query: {  }, copyIndexes:  } 

Vedi http://docs.mongodb.org/manual/reference/command/cloneCollection/

Di solito lo faccio:

 use sourcedatabase; var docs=db.sourcetable.find(); use targetdatabase; docs.forEach(function(doc) { db.targettable.insert(doc); }); 

So che questa domanda ha avuto risposta, ma personalmente non avrei risposto @JasonMcCays a causa del fatto che i cursori trasmettono e questo potrebbe causare un loop infinito del cursore se la raccolta è ancora in uso. Invece vorrei usare uno snapshot ():

http://www.mongodb.org/display/DOCS/How+to+do+Snapshotted+Queries+in+the+Mongo+Database

Anche la risposta @bens è buona e funziona bene per i backup hot delle collezioni, ma mongorestore non ha bisogno di condividere lo stesso mongod.

Questo potrebbe essere solo un caso speciale, ma per una raccolta di documenti di 100k con due campi di stringa casuali (la lunghezza è di 15-20 caratteri), l’uso di una mappa muta è quasi due volte più veloce di find-insert / copyTo:

 db.coll.mapReduce(function() { emit(this._id, this); }, function(k,vs) { return vs[0]; }, { out : "coll2" }) 

È ansible utilizzare il framework di aggregazione per risolvere il problema

 db.oldCollection.aggregate([{$out : "newCollection"}]) 

Va notato che gli indici di oldCollection non verranno copiati in newCollection.

Usando pymongo, devi avere entrambi i database sullo stesso file, ho fatto quanto segue:


db = database originale
db2 = database da copiare

 cursor = db[""].find() for data in cursor: db2[""].insert(data) 

Questo non risolverà il tuo problema ma la shell copyTo ha un metodo copyTo che copia una raccolta in un’altra nello stesso database :

 db.mycoll.copyTo('my_other_collection'); 

Si traduce anche da BSON a JSON, quindi mongodump / mongorestore è il modo migliore per andare, come altri hanno già detto.

Se alcuni utenti di heroku si imbattono qui e come me vogliono copiare alcuni dati dal database di staging al database di produzione o viceversa, ecco come lo si fa in modo molto comodo (NB: spero che non ci siano errori di battitura, non riesco a controllarlo, Cercherò di confermare la validità del codice al più presto):

 to_app="The name of the app you want to migrate data to" from_app="The name of the app you want to migrate data from" collection="the collection you want to copy" mongohq_url=`heroku config:get --app "$to_app" MONGOHQ_URL` parts=(`echo $mongohq_url | sed "s_mongodb://heroku:__" | sed "s_[@/]_ _g"`) to_token=${parts[0]}; to_url=${parts[1]}; to_db=${parts[2]} mongohq_url=`heroku config:get --app "$from_app" MONGOHQ_URL` parts=(`echo $mongohq_url | sed "s_mongodb://heroku:__" | sed "s_[@/]_ _g"`) from_token=${parts[0]}; from_url=${parts[1]}; from_db=${parts[2]} mongodump -h "$from_url" -u heroku -d "$from_db" -p"$from_token" -c "$collection" -o col_dump mongorestore -h "$prod_url" -u heroku -d "$to_app" -p"$to_token" --dir col_dump/"$col_dump"/$collection".bson -c "$collection" 

Questo può essere fatto usando il metodo db.copyDatabase di Mongo:

 db.copyDatabase(fromdb, todb, fromhost, username, password) 

Riferimento: http://docs.mongodb.org/manual/reference/method/db.copyDatabase/

Puoi sempre usare Robomongo. A partire dalla v0.8.3 c’è uno strumento che può farlo facendo clic con il tasto destro sulla raccolta e selezionando “Copia raccolta nel database”

Per i dettagli, vedi http://blog.robomongo.org/whats-new-in-robomongo-0-8-3/

Questa funzione è stata rimossa in 0.8.5 a causa della sua natura bacata, quindi dovrai usare 0.8.3 o 0.8.4 se vuoi provarlo.

Se la RAM non è un problema utilizzando insertMany è molto più veloce di forEach loop.

 var db1 = connect(':/') var db2 = connect(':/') var _list = db1.getCollection('collection_to_copy_from').find({}) db2.collection_to_copy_to.insertMany(_list.toArray()) 

Nel mio caso, ho dovuto usare un sottoinsieme di attributi della vecchia collezione nella mia nuova collezione. Così ho finito per scegliere quegli attributi mentre chiamavo insert sulla nuova collezione.

 db..find().forEach(function(doc) { db..insert({ "new_field1":doc.field1, "new_field2":doc.field2, .... }) });` 

per raccolte di dimensioni enormi, puoi utilizzare Bulk.insert ()

 var bulk = db.getSiblingDB(dbName)[targetCollectionName].initializeUnorderedBulkOp(); db.getCollection(sourceCollectionName).find().forEach(function (d) { bulk.insert(d); }); bulk.execute(); 

Questo farà risparmiare un sacco di tempo . Nel mio caso, sto copiando la raccolta con 1219 documenti: iter vs Bulk (67 secondi contro 3 secondi)