Как скопировать коллекцию из одной базы данных в другую в MongoDB

есть ли простой способ сделать это?

17 ответов


на данный момент в MongoDB нет команды, которая сделала бы это. Обратите внимание на Jira билет с соответствующей функцией запроса.

вы можете сделать что-то вроде:

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

обратите внимание, что при этом две базы данных должны будут использовать один и тот же mongod для работы.

кроме того, вы можете сделать mongodump коллекции из одной базы данных, а затем mongorestore коллекцию в другую базу данных.


лучший способ-сделать mongodump, а затем mongorestore.

вы можете выбрать коллекцию через:

mongodump -d some_database -c some_collection

[дополнительно, zip дамп (zip some_database.zip some_database/* -r) и scp это в другом месте]

затем восстановить ее:

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

существующие данные в some_or_other_collection будут сохранены. Таким образом, вы можете "добавить" коллекцию из одной базы данных в другую.

до версии 2.4.3 вам также нужно будет добавить свои индексы после копирования ваших данных. Начиная с 2.4.3, этот процесс является автоматическим, и вы можете отключить его с помощью --noIndexRestore.


на самом деле, есть is команду движение коллекция из одной базы данных в другую. Это просто не называется "переместить" или "копировать".

чтобы скопировать коллекцию, вы можете клонировать ее в той же БД, а затем переместить клон.

клонировать:

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

для перемещения:

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

другие ответы лучше для копирования коллекции, но это особенно полезно, если вы хотите, чтобы переместить его.


Я бы злоупотребил функцией connect в mongo cli монго док. это означает, что вы можете запустить одно или несколько соединений. если вы хотите скопировать коллекцию клиентов с test на test2 на одном сервере. сначала вы начинаете Mongo shell

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

сделайте нормальный поиск и скопируйте первую запись 20 в test2.

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

или фильтр по некоторым критериям

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

просто измените localhost на IP или имя хоста для подключения к удаленному серверу. Я использую это для копирования тестовые данные в тестовую базу данных для тестирования.


Если между двумя удаленными экземплярами mongod, используйте

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

см.http://docs.mongodb.org/manual/reference/command/cloneCollection/


обычно я делаю:

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

Я знаю, что на этот вопрос был дан ответ, однако я лично не буду делать ответ @JasonMcCays из-за того, что cursors stream и это может вызвать бесконечный цикл курсора, если коллекция все еще используется. Вместо этого я бы использовал snapshot ():

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

@Bens ответ также хороший и хорошо работает для горячих резервных копий коллекций не только это, но и mongorestore не нужно делиться тем же mongod.


это может быть только частный случай, но для коллекции 100k документов с двумя случайными строковыми полями (длина 15-20 символов) использование немого mapreduce почти в два раза быстрее, чем find-insert/copyTo:

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

вы можете использовать aggregation framework для решения проблемы

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

следует отметить, что индексы из oldCollection не будут скопированы в newCollection.


используя pymongo, вам нужно иметь обе базы данных на одном mongod, я сделал следующее:


db = исходная база данных
в DB2 = база данных для копирования в

cursor = db["<collection to copy from>"].find()
for data in cursor:
    db2["<new collection>"].insert(data)

это не решит вашу проблему, но оболочка mongodb имеет copyTo метод, который копирует коллекцию в еще один в той же базе данных:

db.mycoll.copyTo('my_other_collection');

Он также переводится с BSON на JSON, так что mongodump/mongorestore - лучший способ пойти, как сказали другие.


в случае, если некоторые пользователи heroku спотыкаются здесь и, как я, хотят скопировать некоторые данные из промежуточной базы данных в производственную базу данных или наоборот, вот как это сделать очень удобно (N. B. Я надеюсь, что там нет опечаток, не могу проверить его atm., Я постараюсь подтвердить действительность кода как можно скорее):

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"

Это можно сделать с помощью Монго в db.copyDatabase способ:

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

ссылка:http://docs.mongodb.org/manual/reference/method/db.copyDatabase/


вы всегда можете использовать Robomongo. Начиная с v0.8.3 существует инструмент, который может сделать это, щелкнув правой кнопкой мыши на коллекции и выбрав "копировать коллекцию в базу данных"

Подробнее см. В разделе http://blog.robomongo.org/whats-new-in-robomongo-0-8-3/

эта функция была удалены в 0.8.5 из-за его багги природы, так что вам придется использовать 0.8.3 или 0.8.4, если вы хотите попробовать его.


Если ОЗУ не является проблемой, используя insertMany намного быстрее, чем forEach петли.

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())

в моем случае, мне пришлось использовать подмножество атрибутов из старой коллекции в моей новой коллекции. Поэтому я выбрал эти атрибуты при вызове insert в новой коллекции.

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

для огромных коллекций размеров вы можете использовать навалом.insert ()

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

Это позволит сохранить много времени. В моем случае я копирую коллекцию с 1219 документами: iter vs Bulk (67 secs vs 3 secs)