You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mongoid能否重写updated_at时间戳?Rake任务手动修改字段问题

在Mongoid中手动重写updated_at时间戳的方法

当然可以在Mongoid里手动修改updated_at字段!不过默认情况下Mongoid会自动维护这个时间戳(每次保存/更新时都会覆盖成当前时间),所以得用一些特殊方式绕过自动更新机制,我给你两种实用方案:

方案1:使用MongoDB原生set操作(推荐)

这种方法直接在数据库层面修改字段,不会触发Mongoid的自动时间戳逻辑,效率很高,适合单独修改某个文档的场景:

# 直接设置主文档的updated_at为你需要的时间
thisCampaign.set(updated_at: Time.parse(data_hash["updated_at"]))

如果是修改嵌套的channels里的updated_at,也可以用set精准定位嵌套字段:

# 示例:修改第一个channel的updated_at
thisCampaign.set("channels.0.updated_at", Time.parse(data_hash["channels"][0]["updated_at"]))

方案2:临时禁用自动时间戳(适合批量操作)

如果你需要批量修改多个文档或嵌套字段,同时不想让主文档的updated_at被自动更新,可以用skip_timestamping块临时禁用整个模型的时间戳自动维护:

task :campaigns_updated_at_recovery => :environment do
  Dir.foreach('db/raw-data/campaigns/') do |json|
    next if json == '.' or json == '..'
    file = File.read("db/raw-data/campaigns/#{json}")
    data_hash = JSON.parse(file)
    
    thisCampaign = Campaign.find(data_hash["_id"])
    
    # 临时禁用Campaign模型的自动时间戳
    Campaign.skip_timestamping do
      thisCampaign.channels.each_with_index do |chan, idx|
        # 把JSON里的字符串时间转成Time对象
        current_chan_updated_at = Time.parse(chan["updated_at"])
        if current_chan_updated_at < Date.new(2018, 4, 19)
          # 从原始数据中取正确的updated_at值并赋值
          correct_updated_at = Time.parse(data_hash["channels"][idx]["updated_at"])
          chan.updated_at = correct_updated_at
        end
      end
      # 保存时不会自动更新主文档的updated_at
      thisCampaign.save!
    end
  end
end

注意事项

  • 从JSON读取的时间是字符串格式,一定要转成Time或DateTime对象再赋值,否则Mongoid可能无法正确识别。
  • skip_timestamping块会禁用整个模型的自动时间戳,块内的所有保存操作都不会更新created_at和updated_at,块结束后会自动恢复默认行为,不需要手动重置。

内容的提问来源于stack exchange,提问作者RayedB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 08:11:18