【问题标题】:Backup/Restore Collection in Parts部分备份/恢复集合
【发布时间】:2016-02-28 11:19:31
【问题描述】:

我目前正在使用 AWS EC2 服务器,我抓取了一些存储在 MongoDB 集合中的数据。这是我数据库中唯一的集合。

现在我需要将这个集合传输到我的本地机器来处理它。我的问题是远程机器上剩余的磁盘空间不足以转储整个集合。有大约 60% 的收藏空间。 我尝试使用db.copy()db.export() 使用主机名直接在我的本地计算机上复制,但它不起作用,因为我不在本地网络上,并且我有一些身份验证问题,即使使用 ssh 隧道也是如此。

我想做的是将我的大集合分成 2 个较小的集合并转储每个集合。有可能吗?

谢谢!

【问题讨论】:

  • 为什么不直接从您的机器或其他主机连接到主机并将数据转储到那里?您不必在同一台机器上转储,只要可以连接到实例的任何东西。数据库转储/备份等也不是编程主题。请改用dba.stackexchange.com 询问。并不是说任何人都会以不同的方式回答。您只需要允许其他一些主机连接。解决身份验证问题是您的问题,本地主机访问不应该成为问题。或者,天哪,只需将输出通过管道传输到主机可以连接的某个地方。
  • 或者当然是认真地使用范围查询转储您可以在磁盘上容纳的部分数据,然后根据需要迁移文件。大概您有权从该主机上获取结果转储,因此,如果您至少有此权限,那么我看不出上述任何一个问题的原因。
  • 感谢您的快速回答。我对 MongoDB 很陌生,两天前开始使用它。范围查询听起来像是解决我的问题的一个非常简单的方法,我将对此进行调查。

标签: mongodb amazon-ec2


【解决方案1】:

您最好的选择是使用mongodump 来获取收藏的一部分。这也是数据“批量迁移”的最佳选择,因此如果您可以更改主机之间的网络设置以允许这样做,那么有一些使用部分可以应用于直接在主机之间工作。

如果您只需要在集合的一部分上使用mongodump,那么一般情况是应用--query 选项来选择您的输出。输出没有“限制”修饰符,因此您需要应用“范围查询”运算符,它们分别是 $lte$gt

作为一个简单的示例集,考虑以下数据:

{ "_id" : ObjectId("560e4a56a1a451fc8a37057f"), "list" : [ 1, 2, 3 ] }
{ "_id" : ObjectId("560e4a5ca1a451fc8a370580"), "list" : [ 1, 2 ] }
{ "_id" : ObjectId("560e4a62a1a451fc8a370581"), "list" : [ 1 ] }
{ "_id" : ObjectId("560e4a6ca1a451fc8a370582"), "list" : [ ] }

所以想法是在您想要的“切点”处获取_id 值,并构造范围查询以仅选择这些范围内的文档。对于这个例子,我们只是将输出分成两组。

所以你想要的第一件事是第二个文档的_id(在两个文件中),你可以通过在 mongo shell 中应用 .skip().limit() 来检索它:

db.sample.find().sort({ "_id": 1 }).skip(1).limit(1)

这只是要返回文档:

{ "_id" : ObjectId("560e4a5ca1a451fc8a370580"), "list" : [ 1, 2 ] }

这是通过将n-1文档跳过到您要在这批中导出的编号,然后只输出最后一个文档来完成的。

发出的mongodump 将包含$lte 的范围选择器,以达到该点:

mongodump -d test -c sample \
--query '{ "_id": { "$lte": { "$oid": "560e4a5ca1a451fc8a370580" } } }' \
--out part1

注意查询中的$oidmongodumpmongoimport 工具都使用MongoDB Extended JSON 中描述的"strict" 形式。像ObjectId() 这样可用于shell 的辅助构造函数不是“严格意义上的JSON”,而像mongodump(或任何带有--query 选项的工具)这样的工具只是使用JSON 作为输入,因此这些数据以这种形式表示。

对于您的下一点,您希望获得下一个可以放入转储的n 文档。因此,您想通过跳过已经输出的n 文档以及到下一个截止点n-1 的文档数来查询下一个文档截止点,或者基本上是( 2 + 2 -1 ) = 3

db.sample.find().sort({ "_id": 1 }).skip(3).limit(1)

或者更好的是,使用您上次截止的$gt 应用范围:

db.sample.find({ "_id": { "$gt": ObjectId("560e4a5ca1a451fc8a370580") }}).skip(1).limit(1)

无论哪种方式都可以为您提供下一个截止文档:

{ "_id" : ObjectId("560e4a6ca1a451fc8a370582"), "list" : [ ] }

然后对转储应用另一个范围查询,但这次使用“两者”$gt$lte 运算符:

mongodump -d test -c sample \
--query '{ "_id": { 
    "$gt": { "$oid": "560e4a5ca1a451fc8a370580" },
    "$lte": { "$oid": "560e4a6ca1a451fc8a370582" } }}' \
--out part2

与每个部分一样,您可以根据需要获取数据并将其移动到目标主机。请注意,在这种形式中,--out 指定了文件所在的目录

请注意,这里也有一些可以提供帮助的选项,例如:

--host-(最好来自mongorestore)这可以让您在另一个系统上运行整个过程。因此,例如,您可以在新的目标 MongoDB 实例中运行以下命令,将数据从源主机直接传送到该系统上的 mongorestore

mongodump --host orighost -d test -c sample \
--query '{ "_id": { 
    "$gt": { "$oid": "560e4a5ca1a451fc8a370580" },
    "$lte": { "$oid": "560e4a6ca1a451fc8a370582" } }}' \
--out - \
| mongorestore -d newtest -c newsample --dir -

注意- 分别表示每个命令的标准输出/输入。

--gzip - 如果您在两台主机上都有 MongoDB 3.2,那么您还可以利用此选项来压缩/解压缩数据输出或流,如上面的管道。结合该管道选项,这将是将数据迁移到新目标主机的最有效方式。

对于mongorestore,一般来说,无论您如何应用它,数据都会很高兴地重建集合,即使是部分重建。一般行为标记为"Insert Only",因此不同的还原将“添加”到集合中,但不会“覆盖”具有相同_id值的数据。

仔细查看选项。特别是如果您的主机系统都在 EC2 上,甚至都在通用云资源中,那么您确实没有理由不能将输出从一个直接传送到另一个。最多只需要在允许的主机之间进行一点防火墙配置即可。

但无论如何,如果您只想备份“部分”数据,那么这通常是解决问题的方法。

当然,根据您自己的设置和身份验证需求,这两个命令可能需要除此处演示的选项之外的其他选项。这里的选项只是“必需”选项,以便从“数据库”中指定“集合”并使用“查询”进行过滤。

【讨论】:

  • 嗨!感谢您提供超级完整的答案,效果很好。我只是认为您对 mongodump #2 犯了一个错误。 Indee,在第二个截止文档上只使用$gt查询剩余文档就足够了。再次感谢!
  • @ThomasReynaud 没错。它是通过示例完成的,可以根据需要执行任意数量的部分,而不仅仅是 2 个。确实,您不需要在“结束”处使用 $gt,但这不是我要传达的内容。
猜你喜欢
  • 1970-01-01
  • 2020-04-03
  • 2011-07-14
  • 1970-01-01
  • 2011-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多