MongoDB中批量修正数据的正确姿势
MongoDB中批量修正数据的正确姿势

MongoDB中批量修正数据的正确姿势

前言

在Oracle、MySQL中我们有一套标准数据修复流程,这一套流程主要是为了

  1. 能按照需求正确地更新数据至正常。
  2. 更新过程不会对线上造成性能影响
  3. 如果更新错误希望能够回滚到更新前(备份)

在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底层做了特殊的优化。