如何在MongoDB中将集合从一个数据库复制到另一个数据库

时间:2012-07-19 05:58:52

标签: mongodb

有一种简单的方法吗?

20 个答案:

答案 0 :(得分:264)

最好的方法是做一个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禁用它。

答案 1 :(得分:180)

目前MongoDB中没有命令可以执行此操作。请注意JIRA ticket with related feature request

您可以执行以下操作:

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

请注意,有了这个,两个数据库需要共享相同的mongod才能工作。

除此之外,您可以从一个数据库执行集合的mongodump,然后将集合mongorestore存储到另一个数据库。

答案 2 :(得分:84)

实际上, 命令集合从一个数据库移动到另一个数据库。它不被称为“移动”或“复制”。

要复制集合,可以在同一个数据库上克隆它,然后移动克隆。

要克隆:

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

其他答案更适合复制集合,但如果您想要移动它,这尤其有用。

答案 3 :(得分:22)

我会滥用mongo cli mongo doc中的connect函数。这意味着您可以启动一个或多个连接。 如果要将客户集合从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或主机名即可连接到远程服务器。我使用它将测试数据复制到测试数据库进行测试。

答案 4 :(得分:18)

我通常会这样做:

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

答案 5 :(得分:18)

如果在两个远程mongod实例之间,请使用

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

请参阅http://docs.mongodb.org/manual/reference/command/cloneCollection/

答案 6 :(得分:5)

我知道这个问题已经得到解答但是我个人不会做@JasonMcCays的答案,因为游标流是一个事实,如果集合仍然被使用,这可能会导致无限的游标循环。相反,我会使用快照():

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

@bens答案也是一个很好的答案,适用于集合的热备份,不仅如此,但mongorestore不需要共享同一个mongod。

答案 7 :(得分:5)

这可能只是一个特例,但是对于包含两个随机字符串字段(长度为15-20个字符)的100k文档的集合,使用愚蠢的mapreduce几乎是find-insert / copyTo的两倍:

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

答案 8 :(得分:4)

使用pymongo,你需要在同一个mongod上有两个数据库,我做了以下几点:

db =原始数据库
  db2 =要复制到

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

答案 9 :(得分: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=-

如果您运行共享集群,默认情况下不会对新集合进行分片。所有数据最初都写入您的主分片。这可能会导致磁盘空间问题,并为 balancing 增加集群负载。在导入数据之前,最好像这样pre-split您的收藏:

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

答案 10 :(得分:3)

对于庞大的收藏集,您可以使用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秒vs 3秒)

答案 11 :(得分:2)

这不会解决您的问题,但是mongodb shell有一个copyTo方法,可以将一个集合复制到同一个数据库中的另一个

db.mycoll.copyTo('my_other_collection');

它也会从BSON转换为JSON,因此mongodump / mongorestore是最好的方式,正如其他人所说的那样。

答案 12 :(得分:2)

如果使用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())

答案 13 :(得分:1)

如果有些heroku用户在这里绊倒并且像我一样想要将一些数据从登台数据库复制到生产数据库,反之亦然,这里你怎么做得非常方便(注意我希望没有错别字在那里,不能检查它。我会尽快确认代码的有效性:

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"

答案 14 :(得分:1)

有多种方法可以执行集合副本。请注意,副本可以发生在同一数据库,不同数据库,分片数据库或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 shell运行。

参考: The MongoDB Manual

您还可以使用最喜欢的编程语言(例如Java)或环境(例如NodeJS),并使用适当的驱动程序软件编写程序来执行复制-这可能涉及使用查找和插入操作或其他方法。也可以从mongo shell执行此查找插入。

您还可以使用GUI程序(如MongoDB Compass)进行集合副本。

答案 15 :(得分:1)

你总是可以使用Robomongo。从v0.8.3开始,有一个工具可以通过右键单击集合并选择“将集合复制到数据库”来实现此目的

有关详细信息,请参阅http://blog.robomongo.org/whats-new-in-robomongo-0-8-3/

此功能由removed in 0.8.5 {{3}}引起,因为它有缺陷,所以如果你想尝试一下,你必须使用0.8.3或0.8.4。

答案 16 :(得分:0)

就我而言,我必须在新集合中使用旧集合中的一部分属性。所以我在新集合上调用insert时最终选择了这些属性。

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

答案 17 :(得分:0)

使用“ Studio3T for MongoDB” 通过单击数据库,集合或特定集合具有导出和导入工具 下载链接:https://studio3t.com/download/

答案 18 :(得分:0)

要将集合 (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

答案 19 :(得分:-1)

这可以使用Mongo的db.copyDatabase方法完成:

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

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