前言
在Oracle、MySQL中我们有一套标准数据修复流程,这一套流程主要是为了
- 能按照需求正确地更新数据至正常。
- 更新过程不会对线上造成性能影响
- 如果更新错误希望能够回滚到更新前(备份)
在MongoDB中也应该有同样的一套标准化流程,日常更数据一定要按照这个流程来。
通常一个合理的更新流程应该是这样的:
创建临时表
根据实际实际需求筛选出合理的数据,然后重新写到临时表, 这部分数据是需要修正的对象, 如果需要将大量数据都更新为相同值的话则一条update语句足矣,但是日常大部分情况是不同的ID可能需要更新为不同的数据,OUT其实类似关系型数据库中的CTAS。
db.ycf_info.aggregate([
{ $match : { user_id : { $lte : 10 } } }
{ $out : { db : "test", coll : "ycf_info_tmp"} }
])
更新前备份表
如果表数据量比较大,也可以只备份设计到更新的记录
db.user_extra_info.aggregate(
[ { $out : { db : "test", coll : "user_extra_info_bak"} } ]
)
开始更新
注意这里过滤条件要有索引,否则每次更新都是全表扫。
db.ycf_info.find().forEach(
function(myDoc) {
db.user_extra_info.updateOne(
{user_id: myDoc.user_id},
{$set: {diamond: myDoc.diamond}}
);
}
);
补充说明
备份表的时候还有如下一种方法(不推荐):
use pay_db
db.ServerInfo.find().forEach(
function(myDoc){
db.getSiblingDB('test')['ycf_ServerInfo_20230720'].insert(myDoc);
}
)
这里其实想把表数据备份到test库中,但是只限于只有少量数据量(小于1000条),因为insert会非常慢,其实不推荐这种方式,要擅于利用聚合框架(aggregate)中的out操作符,out操作服速度上很多,类比Oracle中的CTAS,Oracle中的CTAS也普通的insert xx select xx方式要快很多,因为Oracle对CTAS底层做了特殊的优化。