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
相关产品推荐
相关产品推荐

