MongoDB 大数据备份,新手教程

MongoDB 大数据备份,新手教程
在 MongoDB 中将数据复制到备份集合归档集合方案有很多种操作流程与示例演示1、方案介绍方案一$merge最推荐原子操作$merge是 MongoDB 4.2 引入的特性可以将聚合管道的结果写入指定的集合。当目标集合和源集合在同一个数据库时这是性能最高的方式因为它完全在数据库引擎内部完成。目标将sales集合中 2024 年的所有文档复制到sales_archive_2024集合。use your_database; // 1. 执行复制操作 db.sales.aggregate([ { $match: { create_time: { $gte: ISODate(2024-01-01T00:00:00Z), $lt: ISODate(2025-01-01T00:00:00Z) } } }, { $merge: { into: sales_archive_2024, // 目标集合名 on: _id, // 基于_id去重防止重复插入 whenMatched: replace, // 如果_id已存在则覆盖 whenNotMatched: insert // 如果不存在则插入 } } ]);参数详解on: _id指定用_id字段来判断文档是否已存在这是防止意外重复执行导致数据翻倍的关键。whenMatched: replace如果目标集合中已存在相同_id的文档就用新文档覆盖它。这保证了操作的幂等性你可以安全地多次执行。whenNotMatched: insert如果不存在则正常插入。验证执行后你可以通过以下命令快速确认复制的数据量是否一致。// 统计源集合中2024年的文档数 db.sales.countDocuments({ create_time: { $gte: ISODate(2024-01-01T00:00:00Z), $lt: ISODate(2025-01-01T00:00:00Z) } }); // 统计归档集合中的文档数 db.sales_archive_2024.countDocuments();方案二find()insertMany()适合较旧版本或小批量数据方案三bulkWrite分批处理处理大数据集的安全方式如果数据量巨大千万级以上且因某些原因不能使用$merge用bulkWrite结合skip/limit进行分批复制是最安全的。const batchSize 5000; let processed 0; let hasMore true; while (hasMore) { // 每次从源表取5000条 const batch db.sales.find({ create_time: { $gte: ISODate(2024-01-01T00:00:00Z), $lt: ISODate(2025-01-01T00:00:00Z) } }).skip(processed).limit(batchSize).toArray(); if (batch.length 0) { hasMore false; break; } // 构建批量插入操作 const operations batch.map(doc ({ insertOne: { document: doc } })); db.sales_archive_2024.bulkWrite(operations, { ordered: false }); processed batch.length; print(已复制 ${processed} 条文档...); }2、复制后的清理与空间回收完成复制并验证数据完整性后就可以安全地删除源数据了。2.1 删除源数据分批进行// 同样建议分批删除避免大事务 const sixMonthsAgo new Date(); sixMonthsAgo.setMonth(sixMonthsAgo.getMonth() - 6); while (db.sales.find({ create_time: { $lt: sixMonthsAgo } }).count() 0) { db.sales.deleteMany({ create_time: { $lt: sixMonthsAgo } }, { limit: 5000 }); sleep(100); // 每批暂停100ms }2.2 回收磁盘空间维护窗口执行删除操作后MongoDB 的磁盘空间不会自动释放。你需要执行压缩// 在主节点执行会阻塞读写建议在从节点执行或安排维护时间 db.runCommand({ compact: sales });3、演示示例3.1 MongoDB控制台操作1、连接操作台 mongosh mongodb://localhost:27017 2、显示数据库 show databases 3、切换到指定数据库如果不存在则创建 use database_name 4、查看当前所使用的数据库 db 5、显示当前数据库中的所有集合 show collections3.2 复制集合操作如下命令db.t_order_package.aggregate([ { $match: { date: { $gte: 2025-01-01, $lte: 2025-12-31 } //日期大于等于“2025-01-01”小于等于“2025-12-31” } }, { $merge: { into: t_order_package_2025,// 目标集合名 on: _id,// 基于_id去重防止重复插入 whenMatched: replace,// 如果_id已存在则覆盖 whenNotMatched: insert// 如果不存在则插入 } } ]);这样操作后会将集合“t_order_package”按照条件复制内容到“t_order_package_2025”集合里注几百万的数据量也是可以直接复制的3.3 验证数据集//按指南条件查询原数据集的数据量 db.t_order_package.countDocuments({ date: { $gte: 2025-01-01, $lte: 2025-12-31 } }); // 统计归档集合数据量 db.t_order_package_2025.countDocuments(); //若他们数据量相等说明复制正确3.4 删除原数据集的数据//尽量分批操作 db.t_order_package.deleteMany({date:{$lte:2024-12-31}}); //指定条件查询原数据集的数据量 db.runCommand({compact:t_order_package});3.5 回收磁盘空间db.runCommand({compact:t_order_package}); //这类似mysql的OPTIMIZE操作4、MongoDB常用的比较操作符常用操作符操作符含义类比 SQL$gt大于 (Greater Than)$gte大于等于(Greater Than or Equal)$lt小于 (Less Than)$lte小于等于(Less Than or Equal)$eq等于(Equal)$ne不等于(Not Equal)!$in在...之中(In)IN$nin不在...之中(Not In)NOT IN示例// 1. 查询 2024-01-01 之后的数据不含当天 db.orders.find({ date: { $gt: 2024-01-01 } }); // 2. 查询 2024-01-01 及之后的数据含当天 db.orders.find({ date: { $gte: 2024-01-01 } }); // 3. 查询 2024-12-31 之前的数据不含当天 db.orders.find({ date: { $lt: 2024-12-31 } }); // 4. 查询 2024-01-01 到 2024-12-31 之间含首尾 db.orders.find({ date: { $gte: 2024-01-01, $lte: 2024-12-31 } }); // 5. 查询 status 不等于 0 的数据 db.orders.find({ status: { $ne: 0 } }); // 6. 查询 status 为 0 或 1 的数据 db.orders.find({ status: { $in: [0, 1] } });字符串日期比较的注意事项因为你的date字段是字符串类型如2025-04-05字符串比较是按字典序逐字符比较进行的。// ✅ 正确因为 2024-01-01 2024-12-31 逐位比较 2024-01-01 2024-12-31 // true // ✅ 正确月份和日期是两位数比较没问题 2024-01-01 2024-01-02 // true // ❌ 错误如果月份不是两位数比较会出错 2024-1-1 2024-01-01 // false因为 1 0所以你的数据格式2025-04-05用$gte/$lte是完全安全的。快速记忆GreaterThan GT→ 大于LessThan LT→ 小于加上EEqual → 加上等于所以$gte 大于等于$lte 小于等于5、总结维护时尽量在服务器空闲时操作操作时要细心注意做好备份。备份数据还可以使用mongoexport/mongoimport工具链