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

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


person EasonBlack    schedule 19.07.2012    source источник
comment
Принятый ответ был, пожалуй, лучшим методом еще в 2012 году, но теперь db.cloneCollection () часто оказывается лучшим решением. Здесь есть несколько более свежих ответов, которые относятся к этому, поэтому, если вы пришли сюда из Google (как это сделал я), взгляните на все ответы!   -  person Kelvin    schedule 31.01.2015
comment
Обязательно прочтите и другие ответы, чтобы убедиться, что они соответствуют вашим потребностям, а не только @kelvin в его / ее ситуации.   -  person PW Kad    schedule 04.05.2015
comment
@Naman, каков вариант использования коллекции копий, я имею в виду, что вам нужна какая-либо команда, или это нормально с ручным процессом? для ручного процесса просто установите studio3T, подключите обе базы данных и щелкните правой кнопкой мыши коллекцию, которую вы хотите скопировать, нажмите опцию Копировать коллекцию, а затем перейдите во вторую базу данных, щелкните правой кнопкой мыши каталог Коллекции и выберите опцию Вставить коллекцию.   -  person turivishal    schedule 23.09.2020
comment
@turivishal, это определенно один способ, но инструменты командной строки намного надежнее и имеют немедленную поддержку функций, выпущенных с обновлениями. Кстати, я увеличил вознаграждение в качестве награды за существующий ответ. :)   -  person Naman    schedule 23.09.2020


Ответы (21)


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

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

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

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

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

person Jason McCay    schedule 19.07.2012
comment
Обратите внимание: если вы копировать в оболочку JS документы BSON декодируются в JSON во время процесса, поэтому некоторые документы могут иметь изменения типа. mongodump / mongorestore - вообще лучший подход. - person Stennie; 19.07.2012
comment
Согласовано. Это было больше просто забавное предложение поиграть с оболочкой. Плюс, это не принесет индексов. Если бы я делал это, я бы делал mongodump / mongorestore каждый раз. - person Jason McCay; 19.07.2012
comment
Спасибо. Обратите внимание, что у вас есть опечатка в коде, не закрывающая функцию getSiblingDB. Вот исправленный код: db. ‹Collection_name› .find (). ForEach (function (d) {db.getSiblingDB ('‹new_database›) [' ‹collection_name› '] .insert (d);}); - person Flaviu; 07.10.2012
comment
это хорошо сработало для сброса тестового mongodb из золотой копии между тестовыми запусками. вместо жесткого кодирования имен коллекций вы можете выполнить цикл for для всех имен коллекций, которые вы хотите скопировать, с помощью db.getCollection (name) .find (). forEach и предоставить функцию, которая имеет db.getSiblingDB (otherdb) .getCollection ( имя) .insert (d). - person simbo1905; 05.12.2012
comment
это эффективно для коллекций огромного размера? - person Khalil Awada; 18.12.2016
comment
Как сделать это для всей базы данных, а не по отдельности для каждой коллекции - person Huzaifa Saifuddin; 07.01.2017
comment
Запрос продолжал останавливаться после того, как было перемещено около 70 записей. Пришлось использовать mongodump и mongorestore - person Ali Saeed; 15.04.2017
comment
копировать записи в удаленную базу данных: db. ‹collection_name› .find ({someId: {$ in: [5687,480,796,96]}}). forEach (function (d) {var dbRemote = connect ('‹ToIpOrHost›: ‹Post› '); dbRemote.getSiblingDB (' ‹ToDbName› ') [' ‹toCollectionName› '] .insert (d);}); - person Eugene Kaurov; 08.05.2020
comment
У меня не работает. [2020-10-07 17:39:06] java.lang.Exception: TypeError: Правая часть instanceof не является объектом - person Cililing; 07.10.2020
comment
Для больших коллекций, вроде 800000 записей, требуется много времени. - person Pouria Moosavi; 28.10.2020
comment
Этот код вставляет документы один за другим, это будет ужасно медленно! Я не понимаю, почему за него так много голосов. - person Wernfried Domscheit; 13.05.2021

Лучше всего сделать mongodump, затем mongorestore. Вы можете выбрать коллекцию через:

mongodump -d some_database -c some_collection

[При желании заархивируйте дамп (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.

person Ben    schedule 19.07.2012
comment
Кажется, что mongodump не работает, если у вас есть защищенный паролем экземпляр mongo (и вы должны!) - person Luciano Camilo; 19.06.2017
comment
Он работает с БД, защищенными PW, вам просто нужно передать аутентификацию в параметрах - person Ben; 17.07.2017
comment
Это намного быстрее, чем find / forEach / insert, в моем случае 2 минуты против 2 часов - person Juraj Paulo; 16.10.2017
comment
Передайте имя пользователя для базы данных с параметром --username, но не --password, чтобы получить запрос на ввод пароля. Лучше не вводить пароль в командную строку (в конечном итоге сохраняя его в .bash_history или аналогичном) - person Chanoch; 08.10.2018
comment
Незначительное: я нашел файл в подпапке с именем some_database, поэтому у меня это работает: mongorestore -d some_other_db -c some_or_other_collection dump / some_database / some_collection.bson - person Aviko; 24.12.2018
comment
Нет необходимости сохранять его в файл. Используйте STDOUT и STDIN: mongodump --db=some_database --collection=some_collection --archive=- | mongorestore --nsFrom="some_database.some_collection" --nsTo="some_or_other_database.some_or_other_collection" --archive=- - person Wernfried Domscheit; 01.04.2021

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

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

Чтобы клонировать:

> use db1
switched to db 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'
      }
  );

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

person Anuj Gupta    schedule 29.04.2013
comment
Спасибо, отлично работает! Просто нужен закрывающий апостроф в 'db1.source_collection' - person andrrs; 29.01.2015
comment
Вместо использования admin, за которым следует db.runCommand (... Вы можете выполнить только одну команду, db.adminCommand (... - person Hamid; 17.11.2017
comment
Это не работает для общих коллекций, которые вы не можете переименовать. - person Wernfried Domscheit; 01.04.2021
comment
Копирование коллекции документ за документом займет много времени! - person Wernfried Domscheit; 01.04.2021

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

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 или имя хоста для подключения к удаленному серверу. Я использую это для копирования тестовых данных в тестовую базу данных для тестирования.

person wayne    schedule 31.07.2012
comment
Как я прокомментировал предложение Джейсона, имейте в виду, что если вы копируете в оболочке JS, документы BSON декодируются в JSON во время процесса, поэтому некоторые документы могут иметь изменения типа. Аналогичные соображения существуют и для Ограничения eval, и это будет более медленный процесс для копирования значительных объемов данных между базами данных (особенно на одном сервере). Итак, mongodump / mongorestore FTW :). - person Stennie; 31.07.2012

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

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

См. http://docs.mongodb.org/manual/reference/command/cloneCollection/ < / а>

person es cologne    schedule 16.10.2013

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

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

для коллекций огромного размера вы можете использовать Bulk.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 секунд против 3 секунд)

person nametal    schedule 30.08.2018
comment
это намного лучше, эффективнее, меньше ударов по БД, работает для любого размера набора данных. - person Jeremie; 24.01.2019
comment
Если вы делаете это с более чем 300 тыс. Записей, вам может потребоваться добавить .limit (300000) после поиска и перед foreach. В противном случае система может зависнуть. Я обычно ограничиваю массовые изменения примерно 100 КБ в целях безопасности. Обертывание всего этого в цикле for на основе количества и лимита. - person triunenature; 07.02.2019
comment
Должны ли мы вставлять (One) или предпочесть объемную вставкуMany? - person NiharGht; 29.09.2020

Вы можете использовать фреймворк агрегации для решения вашей проблемы

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

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

person Alexander Makarov    schedule 11.09.2015
comment
Следует также отметить, что любой существующий newCollection удаляется перед вставкой новых данных. - person Wernfried Domscheit; 13.05.2021

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

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

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

person Sammaye    schedule 19.07.2012

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

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

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


db = исходная база данных
db2 = база данных, в которую нужно скопировать

cursor = db["<collection to copy from>"].find()
for data in cursor:
    db2["<new collection>"].insert(data)
person vbhakta    schedule 24.05.2017
comment
это займет много времени, если размер данных огромен. В качестве альтернативы вы можете использовать bulk_insert - person nishant; 18.01.2018
comment
Да, это был просто быстрый и грязный способ, который я нашел для меня, моя база данных была не слишком большой, но и не маленькой и не занимала много времени, но да, вы правы. - person vbhakta; 25.01.2018

Если оперативная память не является проблемой, использование 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())
person Uday Krishna    schedule 28.06.2018

Есть разные способы сделать коллекционную копию. Обратите внимание, что копирование может происходить в той же базе данных, другой базе данных, сегментированной базе данных или mongod экземплярах. Некоторые инструменты могут быть эффективными для копирования коллекций большого размера.

Агрегация с $ merge: записывает результаты конвейера агрегации в указанную коллекцию. Обратите внимание, что копирование может происходить в разных базах данных, даже в сегментированных коллекциях. Создает новую или заменяет существующую коллекцию. Новое в версии 4.2. Пример: db.test.aggregate([ { $merge: { db: "newdb", coll: "newcoll" }} ])

Агрегация с $ out: записывает результаты конвейера агрегации в указанную коллекцию. Обратите внимание, что копирование может происходить только в той же базе данных. Создает новую или заменяет существующую коллекцию. Пример: db.test.aggregate([ { $out: "newcoll" } ])

mongoexport и mongoimport: это инструменты командной строки. mongoexport производит экспорт данных коллекции в формате JSON или CSV. Выходные данные экспорта используются в качестве источника для целевой коллекции с использованием mongoimport.

mongodump и mongorestore: это инструменты командной строки. mongodump утилита предназначена для создания двоичного экспорта содержимого базы данных или коллекции. Программа mongorestore загружает данные из двоичного дампа базы данных, созданного mongodump, в место назначения.

db.cloneCollection (): копирует коллекцию из удаленного mongod экземпляра в текущий mongod экземпляр. Не рекомендуется, начиная с версии 4.2.

db.collection.copyTo (): копирует все документы из коллекции в новую коллекцию (в той же базе данных). Не рекомендуется, начиная с версии 3.0. Начиная с версии 4.2 MongoDB эта команда недействительна.

ПРИМЕЧАНИЕ. Если не указано иное, приведенные выше команды выполняются из mongo оболочки.

Ссылка: Руководство MongoDB.

Вы также можете использовать любимый язык программирования (например, Java) или среду (например, NodeJS) с помощью соответствующего программного обеспечения драйвера для написания программы для выполнения копирования - это может включать использование операций поиска и вставки или другого метода. Этот поиск-вставку также можно выполнить из оболочки mongo.

Вы также можете сделать копию коллекции с помощью программ с графическим интерфейсом, таких как MongoDB Compass.

person prasad_    schedule 19.09.2020

Как указано в других ответах, самым быстрым решением должно быть mongodump / mongorestore. Нет необходимости сохранять дамп на локальный диск, вы можете передать дамп прямо в mongorestore:

mongodump --db=some_database --collection=some_collection --archive=- | mongorestore --nsFrom="some_database.some_collection" --nsTo="some_or_other_database.some_or_other_collection" --archive=-

Если вы запускаете общий кластер, новая коллекция по умолчанию не сегментируется. Все данные изначально записываются в ваш основной шард. Это может вызвать проблемы с дисковым пространством и создать дополнительную нагрузку на ваш кластер для балансировки < / а>. Лучше предварительно разделить свою коллекцию, как это было раньше вы импортируете данные:

sh.shardCollection("some_or_other_database.some_or_other_collection", { <shard_key>: 1 });
db.getSiblingDB("config").getCollection("chunks").aggregate([
   { $match: { ns: "some_database.some_collection"} },
   { $sort: { min: 1 } },
   { $skip: 1 }
], { allowDiskUse: true }).forEach(function (chunk) {
   sh.splitAt("some_or_other_database.some_or_other_collection", chunk.min)
})
person Wernfried Domscheit    schedule 13.04.2021

Это не решит вашу проблему, но оболочка mongodb имеет _1 _ метод, который копирует коллекцию в другую в той же базе данных:

db.mycoll.copyTo('my_other_collection');

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

person Roberto    schedule 11.09.2013
comment
Превосходно. К сожалению, в справочнике по оболочке Mongo этот метод не упоминается. - person pgl; 23.09.2013
comment
Да, я знаю, но оболочка MongoDB прекрасна, если вы наберете db.collname. [TAB], вы увидите все доступные методы для объекта коллекции. этот совет работает со всеми остальными объектами. - person Roberto; 23.09.2013
comment
Проблема в отсутствии помощи для этих команд! Полезно иметь возможность видеть код, хотя и опуская скобки при вызове метода. - person pgl; 24.09.2013
comment
К сожалению, эта команда устарела с версии 3.0. - person Harry; 02.06.2016

В случае, если некоторые пользователи heroku спотыкаются здесь и, как я, хотят скопировать некоторые данные из промежуточной базы данных в производственную базу данных или наоборот, вот как вы это делаете очень удобно (NB, я надеюсь, что там нет опечаток, не могу проверить это 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"
person Timo    schedule 28.09.2014

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

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

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

person dross    schedule 09.12.2013
comment
Эта функция Robomongo все еще нестабильна. Это шанс 50/50 заставить его работать. - person thedp; 23.07.2014
comment
Похоже, это было удалено из 0.8.5 - person Carasel; 07.09.2015

используйте «Studio3T для MongoDB», у которого есть инструменты экспорта и импорта, щелкнув базу данных, коллекции или ссылку для загрузки конкретной коллекции: https://studio3t.com/download/

person Ahmad Hamzavi    schedule 27.01.2019

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

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

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

**Server1:**
myHost1.com 
myDbUser1
myDbPasword1
myDb1
myCollection1

outputfile:
myfile.json 

**Server2:**
myHost2.com 
myDbUser2
myDbPasword2
myDb2
myCollection2 

ты можешь сделать это:

mongoexport  --host myHost1.com --db myDb1 -u myDbUser1  -p myDbPasword1 --collection myCollection1   --out  myfile.json 

тогда:

mongoimport  --host myHost2.com --db myDb2 -u myDbUser2  -p myDbPasword2 --collection myCollection2   --file myfile.json 

Другой случай, используя файл CSV:

Server1:
myHost1.com 
myDbUser1
myDbPasword1
myDb1
myCollection1
fields.txt
    fieldName1
    fieldName2

outputfile:
myfile.csv

Server2:
myHost2.com 
myDbUser2
myDbPasword2
myDb2
myCollection2

ты можешь сделать это:

mongoexport  --host myHost1.com --db myDb1 -u myDbUser1  -p myDbPasword1 --collection myCollection1   --out  myfile.csv --type=csv

добавьте типы столбцов в файл csv (name1.decimal (), name1.string () ..), а затем:

mongoimport  --host myHost2.com --db myDb2 -u myDbUser2  -p myDbPasword2 --collection myCollection2   --file myfile.csv --type csv --headerline --columnsHaveTypes
person Nestor    schedule 04.06.2021

Это можно сделать с помощью метода Mongo db.copyDatabase:

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

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

person nnamdi    schedule 18.11.2014
comment
OP хотел скопировать коллекцию, а не всю базу данных. - person Pat; 29.06.2015