Comment copier une collection d'une base de données à une autre en MongoDB

y a-t-il une façon simple de faire cela?

183
demandé sur royhowie 2012-07-19 09:58:51

17 réponses

pour le moment, il n'y a aucun commandement en MongoDB qui ferait cela. Veuillez noter le billet JIRA avec la demande de caractéristique correspondante .

Vous pourriez faire quelque chose comme:

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

veuillez noter que les deux bases de données devront partager le même mongod pour que cela fonctionne.

en outre, vous pouvez faire un mongodump d'une collection à partir d'une base de données et puis mongorestore la collection de l'autre base de données.

157
répondu Jason McCay 2016-01-12 14:34:05

la meilleure façon est de faire un mongodum puis mongorestore.

vous pouvez sélectionner la collection via:

mongodump -d some_database -c some_collection

[Éventuellement, le code postal du dump ( zip some_database.zip some_database/* -r ) et scp ailleurs]

puis le restaurer:

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

les données existantes dans some_or_other_collection seront préservées. De cette façon, vous pouvez "ajouter" une collection d'une base de données à une autre.

avant la version 2.4.3, vous devrez également ajouter vos index après la copie de vos données. En commençant par 2.4.3, ce processus est automatique, et vous pouvez le désactiver avec --noIndexRestore .

246
répondu Ben 2014-07-10 00:48:30

en fait, il est une commande à déplacer une collection d'une base de données à une autre. Ça ne s'appelle pas "bouger"ou " copier".

pour copier une collection, vous pouvez la cloner sur le même db, puis déplacer le clone.

Pour cloner:

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

Pour se déplacer:

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

les autres réponses sont mieux pour copier la collection, mais c'est surtout utile si vous cherchez à le déplacer.

70
répondu Anuj Gupta 2016-03-22 23:19:12

je ne l'abus de la fonction de connexion à mongo cli mongo doc . ce qui signifie que vous pouvez démarrer une ou plusieurs connexions. si vous voulez copier la collection de clients de test en test2 dans le même serveur. d'abord vous commencez Mongo shell

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

faites une recherche normale et copiez les 20 premiers enregistrements à test2.

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

ou filtrer selon certains critères

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

il suffit de changer le localhost en IP ou nom d'hôte pour se connecter au serveur distant. Je l'utilise pour copier des données de test dans une base de données de test pour le test.

22
répondu wayne 2012-07-31 01:54:39

si entre deux instances distantes de mongod, utilisez

{ cloneCollection: "<collection>", from: "<hostname>", query: { <query> }, copyIndexes: <true|false> } 

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

18
répondu es cologne 2013-10-16 13:07:25

je ferais d'habitude:

use sourcedatabase;
var docs=db.sourcetable.find();
use targetdatabase;
docs.forEach(function(doc) { db.targettable.insert(doc); });
15
répondu amenadiel 2013-08-20 02:19:26

je sais qu'il a été répondu à cette question mais je ne répondrais pas personnellement à @JasonMcCays en raison du fait que les curseurs circulent et que cela pourrait causer une boucle de curseur infinie si la collection est encore utilisée. J'utiliserais plutôt un snapshot ():

http://www.mongodb.org/display/DOCS/How+à+faire+Snapshotted+Requêtes+dans+le+Mongo+Base de données

@bens answer est également un bon et fonctionne bien pour les sauvegardes chaudes de collections non seulement cela, mais mongorestore n'a pas besoin de partager la même mongod.

5
répondu Sammaye 2012-07-19 13:12:12

cela pourrait être juste un cas spécial, mais pour une collection de 100k documents avec deux champs de chaîne de caractères aléatoires (la longueur est de 15-20 caractères), en utilisant un muet mapreduce est presque deux fois plus rapide que find-insert / copyTo:

db.coll.mapReduce(function() { emit(this._id, this); }, function(k,vs) { return vs[0]; }, { out : "coll2" })
5
répondu Vajk Hermecz 2013-06-25 23:22:11

Vous pouvez utiliser l'agrégation cadre de résoudre votre problème

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

Il shoul noter que les indices de oldCollection ne seront pas copiés dans newCollection.

5
répondu Alexander Makarov 2015-09-11 08:14:18

en utilisant pymongo, vous devez avoir les deux bases de données sur le même mongod, j'ai fait ce qui suit:


db = base de données originale

db2 = base de données à copier vers

cursor = db["<collection to copy from>"].find()
for data in cursor:
    db2["<new collection>"].insert(data)
4
répondu vbhakta 2017-06-08 15:44:38

cela ne résoudra pas votre problème mais le shell mongodb a une méthode copyTo qui copie une collection dans une autre dans la même base de données :

db.mycoll.copyTo('my_other_collection');

il traduit aussi de BSON à JSON, donc mongodump / mongorestore sont la meilleure façon d'aller, comme d'autres l'ont dit.

2
répondu Roberto 2014-03-07 13:08:38

dans le cas où certains utilisateurs heroku trébucher ici et comme moi veulent copier certaines données de la base de données de mise en scène à la base de données de production ou vice versa voici comment vous le faites très commodément (N.B. j'espère qu'il n'y a pas de fautes de frappe là-dedans, ne peut pas le vérifier atm. Je vais essayer de confirmer la validité du code asap):

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"
1
répondu Timo 2014-09-28 09:48:53

cela peut être fait en utilisant la méthode db.copyDatabase de Mongo:

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

référence: http://docs.mongodb.org/manual/reference/method/db.copyDatabase /

1
répondu nnamdi 2014-11-18 16:30:15

vous pouvez toujours utiliser Robomongo. À partir de v0.8.3 Il y a un outil qui peut le faire en cliquant avec le bouton droit de la souris sur la collection et en sélectionnant "Copier la Collection vers la base de données"

pour plus de détails, voir http://blog.robomongo.org/whats-new-in-robomongo-0-8-3 /

cette fonctionnalité a été supprimé dans 0.8.5 en raison de sa nature buggy donc vous devrez utiliser 0.8.3 ou 0.8.4 si vous voulez l'essayer.

1
répondu dross 2017-03-30 23:51:55

si la RAM n'est pas un problème en utilisant insertMany est beaucoup plus rapide que forEach boucle.

var db1 = connect('<ip_1>:<port_1>/<db_name_1>')
var db2 = connect('<ip_2>:<port_2>/<db_name_2>')

var _list = db1.getCollection('collection_to_copy_from').find({})
db2.collection_to_copy_to.insertMany(_list.toArray())
1
répondu TheNeverLander 2018-06-28 05:39:41

Dans mon cas, j'ai dû utiliser un sous-ensemble d'attributs de l'ancienne collection dans ma nouvelle collection. J'ai donc fini par choisir ces attributs tout en appelant insert sur la nouvelle collection.

db.<sourceColl>.find().forEach(function(doc) { 
    db.<newColl>.insert({
        "new_field1":doc.field1,
        "new_field2":doc.field2,
        ....
    })
});`
0
répondu dranga 2016-06-24 20:44:48

pour les collections de grande taille, vous pouvez utiliser en vrac.insérer ()

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

Cela permettra d'économiser beaucoup de temps . Dans mon cas, je copie collection avec 1219 documents: iter vs Bulk (67 secondes vs 3 secondes)

0
répondu nametal 2018-08-30 03:32:45