更改Mongoid中的字段类型而不会丢失数据 [英] Change type of field in Mongoid without losing data

查看:192
本文介绍了更改Mongoid中的字段类型而不会丢失数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何运行迁移以更改Mongoid/MongoDB中的字段类型而又不丢失任何数据?

How can I run a migration to change the type of a field in Mongoid/MongoDB without losing any data?

在我的情况下,我试图将BigDecimal(存储为字符串)转换为Integer以存储一些资金.我需要将字符串的十进制表示形式转换为整数的美分.我不想丢失现有数据.

In my case I'm trying to convert from a BigDecimal (stored as string) to an Integer to store some money. I need to convert the string decimal representation to cents for the integer. I don't want to lose the existing data.

我假设这些步骤可能类似于:

I'm assuming the steps might be something like:

  1. 使用新名称(例如amount2
  2. )创建新的Integer字段
  3. 部署到生产并运行迁移(或rake任务),以将每个amount转换为amount2的正确值
  4. (这整个现有代码仍在使用amount,并且从用户的角度来看,没有停机时间)
  5. 关闭站点进行维护,再运行一次迁移以捕获在最近几分钟内可能已更改的所有amount字段
  6. 删除amount并将amount2重命名为amount
  7. 部署新代码,该代码期望amount是整数
  8. 备份网站
  1. create new Integer field with a new name, say amount2
  2. deploy to production and run a migration (or rake task) that converts each amount to the right value for amount2
  3. (this whole time existing code is still using amount and there is no downtime from the users perspective)
  4. take the site down for maintenance, run the migration one more time to capture any amount fields that could have changed in the last few minutes
  5. delete amount and rename amount2 to amount
  6. deploy new code which expects amount to be an integer
  7. bring site back up

Mongoid似乎提供了rename方法: http://mongoid.org /docs/persistence/atomic.html#rename

It looks like Mongoid offers a rename method: http://mongoid.org/docs/persistence/atomic.html#rename

但是我有点困惑如何使用它.如果您有一个名为amount2的字段(并且您已经删除了amount),您是否只是运行Transaction.rename :amount2, :amount?然后,我想这会立即破坏基础表示,因此您必须在那之后重新启动应用程序服务器吗?如果在amount仍然存在的情况下运行该命令,会发生什么情况?它会被覆盖,失败还是尝试自行转换?

But I'm a little confused how this is used. If you have a field named amount2 (and you've already deleted amount), do you just run Transaction.rename :amount2, :amount? Then I imagine this immediately breaks the underlying representation so you have to restart your app server after that? What happens if you run that while amount still exists? Does it get overwritten, fail, or try to convert on it's own?

谢谢!

推荐答案

好的,我做到了.我认为有一种使用mongo控制台的更快的方法,例如: MongoDB:如何更改字段的类型?

Ok I made it through. I think there is a faster way using the mongo console with something like this: MongoDB: How to change the type of a field?

但是我无法进行转换,因此在Rails控制台中选择了这种较慢的方法,并且停机时间更长.如果有人有更快的解决方案,请发布它.

But I couldn't get the conversion working, so opted for this slower method in the rails console with more downtime. If anyone has a faster solution please post it.

  • 使用新名称(例如amount2
  • )创建新的Integer字段
  • 在控制台或rake任务中将每个amount转换为amount2的正确值
  • create new Integer field with a new name, say amount2
  • convert each amount to the right value for amount2 in a console or rake task

Mongoid.identity_map_enabled = false
Transaction.all.each_with_index do |t,i|
  puts i if i%1000==0
  t.amount2 = t.amount.to_money
  break if !t.save
end

请注意,由于mongodb游标,.all.each可以正常工作(您不需要像mysql一样使用.find_each或.find_in_batches进行常规活动记录).只要identity_map处于关闭状态,它就不会填满内存.

Note that .all.each works fine (you don't need to use .find_each or .find_in_batches like regular activerecord with mysql) because of mongodb cursors. It won't fill up memory as long as the identity_map is off.

  • 关闭站点进行维护,再运行一次迁移,以捕获最近几分钟内可能已更改的任何金额字段(例如Transaction.where(:updated_at.gt => 1.hour.ago).each_with_index...

在模型中注释field :amount, type: BigDecimal,您不希望mongoid再次了解此字段,并推送此代码

comment out field :amount, type: BigDecimal in your model, you don't want mongoid to know about this field anymore, and push this code

Mongoid.identity_map_enabled = false
Transaction.all.each_with_index do |t,i|
  puts i if i%1000==0
  t.rename :amount2, :amount
end

这是原子的,不需要在模型上保存.

This is atomic and doesn't require a save on the model.

  • 更新模型以反映新的列类型field :amount, type: Integer
  • 部署并恢复网站

如前所述,我认为有更好的方法,因此,如果有人有一些提示,请分享.谢谢!

As mentioned I think there is a better way, so if anyone has some tips please share. Thanks!

这篇关于更改Mongoid中的字段类型而不会丢失数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆