【问题标题】:What's the fastest way to copy a collection within the same database?在同一数据库中复制集合的最快方法是什么?
【发布时间】:2012-05-16 19:01:15
【问题描述】:

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

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

我知道cloneCollection 命令,但它似乎是为了 仅复制到另一台服务器。

我也知道 mongoimportmongoexport,但由于我是通过 PHP 执行此操作的,因此我不想调用 shell。

【问题讨论】:

  • 正确答案是获得 230 票的那个。
  • db.myoriginal.aggregate([ { $match: {} }, { $out: "mycopy" } ]) 这是比接受的答案更快的答案。
  • 很高兴知道,谢谢。我无法不接受这个答案,但它在 2012 年可能是正确的。$out 需要 2014 年才发布的 MongoDB v2.6。

标签: mongodb


【解决方案1】:
db.myoriginal.aggregate([ { $match: {} }, { $out: "mycopy" } ])

这比在 forEach 循环中进行多次插入要快得多。

【讨论】:

  • 在 i5 PC 上 1-2 分钟内获取 12GB 数据。最好的部分:它是非阻塞的
  • 请注意目标不能是上限集合
  • 谢谢,太好了。请注意,索引将丢失
  • 如何使用此方法将索引包含到新集合中?
  • 为什么要插入 { $match: {} }?。实际上它对我来说没有它(我有 4.2)。
【解决方案2】:

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

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。
  • 我可以尝试使用php.net/manual/en/mongodb.execute.php的脚本方法
  • 使用哑 mapReduce(自映射,无缩减),为我在 mongoexpor 和 script.js 解决方案之间进行测量...
  • Mongodump | mongorestore 应该比 export|import 更快,因为它不必将二进制格式反序列化为 json 或 csv。
  • 复制到targetcollection时如何保留索引?
【解决方案3】:

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


最简单有效的方法是使用copyTo(),所以你可以使用:

db.source.copyTo("target"); 

&如果"target"不存在,就会被创建

-- 更新--

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

-- 更新--

因为CopyTo() 在内部使用eval() 并且eval() 自3.0 版起已弃用,因此CopyTo() 自3.0 版起也已弃用

【讨论】:

  • 直到 v2.6.3 copyTo() 将阻止 mongod 实例上的所有操作。来自文档:> 因为 copyTo() 在内部使用 eval,所以复制操作将阻塞 mongod 实例上的所有其他操作。
  • @YogeshMangaj 感谢您的注意,我更新了答案,以便所有人都能轻松看到。
  • 自 3.0 版后已弃用。
  • 不要这样做。如文档中所述,这将阻止所有写入操作。
  • @lbolla 我几个月前已经在答案中提到了这一点:D
【解决方案4】:

第一个选项(使用 mongo 转储)

  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("回滚完成!");

【讨论】:

  • 前两个选项哪个更快?
【解决方案5】:

除了 AD7six 第一个解决方案,如果您使用 mongoexport / import,请确保您的集合数据类型和 mongo 配置,如下所述:http://docs.mongodb.org/manual/reference/mongodb-extended-json/

【讨论】:

  • 请澄清/说明您希望指出的内容。 Mongoimport 和 mongoexport 使用相同的格式,无需配置,也没有数据变异的风险。
【解决方案6】:

这是我在 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])

【讨论】:

    【解决方案7】:

    最快的方法是db.collection.copyTo()

    请注意,自 3.0 版起已弃用。

    【讨论】:

      【解决方案8】:

      你可以在mongo shell中使用copyDatabase函数:

      http://docs.mongodb.org/manual/tutorial/copy-databases-between-instances/

      【讨论】:

      • 请注意,link-only answers are discouraged,SO 答案应该是搜索解决方案的终点(相对于另一个参考中途停留,随着时间的推移往往会变得陈旧)。请考虑在此处添加独立的概要,并保留链接作为参考。
      猜你喜欢
      • 2019-03-01
      • 2010-09-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-05
      • 2013-04-11
      相关资源
      最近更新 更多