在同一数据库中复制集合的最快方法是什么?


73

我想在同一数据库中复制一个集合,并给它一个不同的名称-基本上拍摄快照。

最好的方法是什么?是否有命令,还是我必须依次复制每个记录?

我知道该cloneCollection命令,但它似乎仅用于复制到另一台服务器。

我也知道mongoimportmongoexport,但是当我通过PHP执行此操作时,我不希望对shell进行调用。


正确的答案是有230票赞成票。
多纳托

Answers:


56

您有几种选择,但是最快的是:

mongodump -d db -c sourcecollection 
mongorestore -d db -c targetcollection --dir=dump/<db>/<sourcecollection.bson>

要么

mongoexport -d db -c sourcecollection | mongoimport -d db -c targetcollection --drop

或在php中:

`mongoexport -d db -c sourcecollection | mongoimport -d db -c targetcollection --drop`;

之后,你有

mongo db < script.js

mongo docs所示,script.js包含以下内容:

db.myoriginal.find().forEach( function(x){db.mycopy.insert(x)} );

复制集合最慢(一个数量级或更多)的方法是使用本机php驱动程序-仅仅是因为移动信息。但是,如果您绝对希望使用db execute函数避免cli调用,则可以发出上述mongo查询。


谢谢。我当前正在使用您的第一个选项,但希望有一个我可以简单调用的命令,因此不需要从PHP调用Shell。
蒂姆(Tim)


1
使用愚蠢的mapReduce(自我映射,不减少),为我在mongoexpor和script.js解决方案之间进行度量...
Vajk Hermecz

1
Mongodump | mongorestore应该比export | import更快,因为它不必将二进制格式反序列化为json或csv。
Cody A. Ray

1
在复制到targetcollection期间如何保留索引?
abdulmanov.ilmir

221
db.myoriginal.aggregate([ { $match: {} }, { $out: "mycopy" } ])

它比在forEach循环中执行许多插入要快得多。


6
在i5 PC上,在1-2分钟内可获得12GB的数据。最好的部分是:它不会阻塞
Stefan Rogin

1
请注意目标不能是上限集合
维塔利·戴亚特洛夫

5
谢谢,太好了。请注意,索引将丢失
kraf

3
如何使用此方法将索引包括到新集合中?
aandis

2
为什么要插入{$ match:{}}?实际上,没有它,它对我有效(我有4.2)。
Alisettar Huseynli,

14

注意:阅读答案更新,它们很重要!


最简单有效的方法是使用copyTo(),因此您可以使用:

db.source.copyTo("target"); 

&如果"target"不存在,它将被创建

-更新-

根据CopyTo Documentation,由于copyTo()内部使用eval,因此复制操作将阻止mongod实例上的所有其他操作。所以它不应该在生产中使用环境中。

-更新-

因为内部CopyTo()使用eval()eval()从3.0版开始不推荐使用,所以CopyTo()也从3.0版开始不推荐使用


4
最高v2.6.3copyTo()将阻止该mongod实例上的所有操作。从文档中:>因为copyTo()在内部使用eval,所以复制操作将阻止mongod实例上的所有其他操作。
Yogesh Mangaj 2014年

1
@YogeshMangaj感谢您的注释,我更新了答案,每个人都可以轻松看到。
AbdelHady 2014年

8
从3.0版开始不推荐使用。
Francesco Casula 2015年

不要这样做。如文档中所述,这将阻止所有写操作。
lbolla

1
@lbolla我已经在几个月前的答案中提到了这个问题:D
AbdelHady

1

第一选择(使用mongo dump)

  1. 从集合中获取转储

    mongodump -d db -c source_collection

  2. 从集合中还原

    mongorestore -d db -c target_collection dir = dump / db_name / source_collection.bson

第二种选择

  1. 运行汇总

    db.getCollection('source_collection')。aggregate([[{$ match:{“ emailAddress”:“ apitester@mailinator.com”}},{$ out:“ target_collection”}])

第三选择(最慢)

  1. 运行直通for循环

    db.getCollection('source_collection')。find()。forEach(function(docs){db.getCollection('target_collection')。insert(docs);})print(“ Rolleback完成!”);



0

这是我在python(pymongo)中的实现:

def copy_collection(client, from_db, from_coll, to_db=None, to_coll=None):
    to_db = from_db if to_db is None else to_db
    to_coll = from_coll if to_coll is None else to_coll
    assert (to_db != from_db or to_coll != from_coll), "Copy Error: Source and destination can't be same!"
    documents = client[from_db][from_coll].find()
    client[to_db][to_coll].insert_many([d for d in documents])


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.