【问题标题】:Is there a way to perform a "dry run" of an update operation?有没有办法执行更新操作的“试运行”?
【发布时间】:2013-05-12 17:10:36
【问题描述】:

我正在更改我的 MongoDB 集合之一的架构。 (我一直将日期存储为字符串,现在我的应用程序将它们存储为ISODates;我需要返回并更改所有旧记录以使用ISODates。)我想我知道该怎么做这使用了更新,但由于此操作会影响数万条记录,所以我很犹豫是否发出一个我不能 100% 确定是否会起作用的操作。有什么方法可以对更新进行“试运行”,以向我展示少量记录的原始记录以及如何更改它?


编辑:我最终使用了向每条记录添加一个新字段的方法,然后(在验证数据正确之后)重命名该字段以匹配原始字段。它看起来像这样:

db.events.find({timestamp: {$type: 2}})
    .forEach( function (e) {
        e.newTimestamp = new ISODate(e.timestamp);
        db.events.save(e);
    } )

db.events.update({},
    {$rename: {'newTimestamp': 'timestamp'}},
    {multi: true})

顺便说一句,将字符串时间转换为ISODates 的方法最终奏效了。 (我从this SO answer得到这个想法。)

【问题讨论】:

  • 我的建议是将 ISODate 添加为新字段。一旦确认一切看起来都不错,您就可以取消设置字符串日期。
  • @JamesWahlin 有正确的想法,即使在支持空运行的 SQL 中我也不会这样做
  • @JamesWahlin 您可以添加您的评论作为答案吗?

标签: mongodb


【解决方案1】:

另一种选择取决于它将导致您的开销 - 您可以考虑编写一个脚本,执行查找操作、添加打印输出或在调试中运行,同时注释掉保存操作。获得信心后,您可以应用保存操作。

 var changesLog = [];
var errorsLog = [];
events.find({timestamp: {$type: 2}}, function (err, events) {
    if (err) {
        debugger;
        throw err;
    } else {
        for (var i = 0; i < events.length; i++) {
            console.log('events' + i +"/"+(candidates.length-1));
            var currentEvent = events[i];
            var shouldUpdateCandidateData = false;

            currentEvent.timestamp = new ISODate(currentEvent.timestamp);


            var change = currentEvent._id;
            changesLog.push(change);

            // // ** Dry Run **
            //     currentEvent.save(function (err) {
            //         if (err) {
            //             debugger;
            //             errorsLog.push(currentEvent._id + ", " + currentEvent.timeStamp + ', ' + err);
            //             throw err;
            //         }
            //     });
        }
        console.log('Done');
        console.log('Changes:');
        console.log(changesLog);
        console.log('Errors:');
        console.log(errorsLog);
        return;
    }
});

【讨论】:

    【解决方案2】:

    我的建议是将 ISODate 添加为新字段。一旦确认一切看起来都不错,您就可以取消设置字符串日期。

    【讨论】:

      【解决方案3】:

      选择您要监控的特定记录的 ID。放在update{_id:{$in:[&lt;your monitored id&gt;]}}

      【讨论】:

      • 这是一种方法,尽管如果我搞砸了更新操作,它仍然有可能破坏数据。
      • @bdesham 在没有备份的情况下试验实时数据是一种不好的做法。这是任何生产操作的拇指规则 - 首先创建回滚点
      【解决方案4】:

      使用您的数据库结构创建一个测试环境。将少量记录复制到其中。问题解决了。我敢肯定,这不是您正在寻找的解决方案。但是,我相信,这正是应该使用“测试环境”的确切情况。

      【讨论】:

      • 我想到了。但是,如果我的第一次尝试没有成功,我将不得不清除开发环境并重新导入数据——可能会多次——这似乎是一个我可以避免的麻烦。
      • 是的,我以为已经考虑过了,只是想我会把建议扔在那里,无论如何……我自己有时会忽略一些简单的东西。
      猜你喜欢
      • 2021-09-29
      • 1970-01-01
      • 1970-01-01
      • 2014-07-16
      • 2019-09-07
      • 1970-01-01
      • 2013-10-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多