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

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

26 ответов

Решение

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

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

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

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

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

Лучше всего сделать 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,

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

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

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

> 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?

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

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

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); });

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

Как указано в других ответах, самым быстрым решением должно быть 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)
})

Вы можете использовать структуру агрегации, чтобы решить вашу проблему

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

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

Есть разные способы сделать коллекционную копию. Обратите внимание, что копирование может происходить в той же базе данных, другой базе данных, сегментированной базе данных или 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.

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


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

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

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

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

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

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

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

Здесь много правильных ответов. я бы пошел на mongodumpа также mongorestoreв кантом для большой коллекции:

      mongodump --db fromDB --gzip --archive | mongorestore --drop --gzip --archive --nsFrom "fromDB.collectionName" --nsTo "toDB.collectionName"

хотя, если я хочу сделать быструю копию, это медленно, но работает:

      use fromDB 
db.collectionName.find().forEach(function(x){
   db.getSiblingDB('toDB')['collectionName'].insert(x);
});"

Если ОЗУ не проблема с использованием 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())

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

db.mycoll.copyTo('my_other_collection');

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

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

Для получения дополнительной информации см. http://blog.robomongo.org/whats-new-in-robomongo-0-8-3/

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

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

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"

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

Начиная с версии 4.2, MongoDB удаляет устаревшиеcopydbкоманда иcloneкоманда.

В качестве альтернативы пользователи могут использовать и (с опциями и ).

Например, чтобы скопировать коллекцию из базы данных вtargetбазе данных, вы можете:

  1. Использоватьmongodumpсброситьtestколлекция изsourceбазу данных в архивtest.agz:
      mongodump --gzip --archive=/backup/path/to/test.agz --db=source --collection=test
  1. Использоватьmongorestoreс--nsFromи--nsToдля восстановления (с изменением имени базы данных) из архива:
      mongorestore --gzip --archive=/backup/path/to/test.agz --nsFrom='source.test' --nsTo='target.test'

ПРИМЕЧАНИЕ. При необходимости обеспечьте аутентификацию с помощью--uriпараметр, если MongoDB работает на внешнем экземпляре, или комбинация--usernameи--passwordпараметры, если MongoDB работает на локальном экземпляре.

Ссылка: mongodump — Инструменты для баз данных MongoDB.

Самый простой способ импортировать данные из существующей БД кластера атласа MongoDB — использоватьmongodump&mongorestoreкоманды.

Чтобы создать дамп из существующей БД, вы можете использовать:

      mongodump --uri="<connection-uri>"

Существуют и другие варианты подключения, которые можно найти здесь: https://www.mongodb.com/docs/database-tools/mongodump/

После того, как дамп успешно создан в каталоге dump/, вы можете импортировать эти данные в другую базу данных следующим образом:

      mongorestore --uri="<connection-uri-of-other-db>" <dump-file-location>

Аналогично для mongorestore существуют другие параметры подключения, которые можно найти вместе с командами для восстановления определенных коллекций: https://www.mongodb.com/docs/database-tools/mongorestore/

Расположение файла дампа будет внутри каталога дампа. Там может быть подкаталог с тем же именем, что и имя БД, которое вы выгрузили. Например, если вы сделали дамп тестовой БД, то расположение файла дампа будет /dump/test.

Я пришел сюда в поисках способа перенести коллекцию, поэтому спасибо user1678159 за вторую часть его решения , основанного наdb.runCommand({renewCollection.... респекты решению user4329230 и особенно комментарию Аналогичные user936452

В остальном я вижу множество решений, основанных на последовательном чтении и записи, которые с привилегированной точки зрения конца 2023 года я бы назвал «Зимним кодом». Все эти дополнительные циклы процессора, конечно, согревают нас... Сюда входят решения, явные, замаскированные курсором илиinitializeUnorderedBulkOp.

Что касается зарубежных инструментов, то я не думаю, что дамп/восстановление или экспорт/импорт — идеальные решения. Они позволяют обойти проблему, избегаяmongosh, что не идеально. Я распространяю эту оценку на такие рекомендации, как Studio3T. Хотя я разработчик Python, мне кажется, что использование mongosh — это еще один обходной путь для тех, кто отказывается изучать mongosh, который на 99,7% представляет собой старый добрый JavaScript. Кроме того,pymongoопубликованное здесь решение также читает и вставляет одно за другим.

В этой же заметке я нашел здесь онлайн-статью , в которой по состоянию на конец мая 2023 года все еще предлагается устаревший метод сбора.copyTo, вместе с кучей разрозненных упоминаний (вродеforEachилиaggregate), которые никогда не развиваются в тему заголовка: « Как скопировать БД и коллекцию? ». Совершенно бесполезно и даже хуже: это часть онлайн-курса, такая бесполезная и безответственная. Следите за ответами, рекомендующими как этот метод, так иdb.copyDatabase. Если ваш питомец — тираннозавр, думаю, они все еще есть у вашего монго.

Мое решение похоже на то, что я видел в user3672229 Кришны . Я просто сделал это как функцию: посте

      function transfer(collection, sourceDb, target_db) {
    db.getSiblingDB(targetDb).getCollection(collection).insertMany(
        db.getSiblingDB(sourceDb).getCollection(collection).find().toArray()
    )
}

Обратите внимание, что это решение даже не требует использования какой-либо из задействованных баз данных. Хитрость здесь заключается в том, чтобы сделать.toArray()в конце, чтобы результат можно было использовать в качестве аргументаinsertMany.

Вы можете использовать функцию агрегации $out, чтобы скопировать все в другую таблицу.

https://www.mongodb.com/docs/manual/reference/operator/aggregation/out/

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

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

Чтобы скопировать коллекцию (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

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

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

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

Другие вопросы по тегам