2012-02-22 56 views
1

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

在我的情况下,我试图从BigDecimal(存储为字符串)转换为Integer来存储一些钱。我需要将字符串十进制表示转换为整数的分。我不想丢失现有的数据。

我假设的步骤可能是这样的:

  1. 创造新的整型字段用一个新的名字,说amount2
  2. 部署到生产环境和运行迁移(或耙任务),其将每个amountamount2
  3. 正确的价值(这整个过程中现有代码仍然使用amount并没有从用户的角度来看停机)
  4. 采取现场检修,运行日Ë迁移一个更多的时间来捕捉,可以在最后几分钟发生了变化
  5. 删除amount和重命名amount2amount
  6. 部署新的代码,预计amount是一个整数
  7. 把网站备份
  8. 任何 amount领域

它看起来像Mongoid提供rename方法:http://mongoid.org/docs/persistence/atomic.html#rename

但我有点困惑这是如何使用的。如果您有一个名为amount2的字段(并且您已删除amount),那么您是否只运行Transaction.rename :amount2, :amount?那么我想这会立刻破坏底层表示,所以你必须在这之后重新启动你的应用服务器?如果你运行的话会发生什么,而amount仍然存在?它会被覆盖,失败或尝试自行转换吗?

谢谢!

+0

听起来合乎逻辑的。但我不确定是否需要重新启动。首先,你需要更新模型中的字段名称? 至于重写,我不知道,但这个链接的更新插入部分http://whyjava.wordpress.com/2012/02/07/how-to-rename-field-in-all-the-mongodb -documents /确实似乎暗示它会尝试写入,并且可能会覆盖该字段(如果存在)。所以它不像常规的基于SQL的重命名,而是单独移动每个文档值。说得通? – 2012-02-22 06:22:50

+0

嗯...不知道,还是想获得工作的例子,从开始到结束。如果我的成功,我会发布一个。 – 2012-02-23 05:03:51

回答

3

好吧,我做到了。我认为这是使用蒙戈控制台是这样一个更快的方法: MongoDB: How to change the type of a field?

但我无法得到的转换工作,所以选择了在轨控制台更多的停机时间这种慢的方式。如果有人有更快的解决方案,请发布。

  • 创造新的整型字段用一个新的名字,说amount2
  • 互相转换amount向右值amount2在控制台或耙任务

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 

请注意.all.each正常工作(您不需要像常规一样使用.find_each或.find_in_batches由于mongodb游标,activerecord与mysql)。只要identity_map关闭,它就不会填充内存。

  • 采取现场检修,运行迁移更多的时间来捕捉,可以在最后几分钟已经改变任何金额字段(类似Transaction.where(:updated_at.gt => 1.hour.ago).each_with_index...

  • 注释掉field :amount, type: BigDecimal在模型中,你不想mongoid了解这个领域了,并推动该代码

  • 现在运行另一个脚本来重命名列(它会覆盖过程中的任何旧的BigDecimal字符串值)。你可能需要的任何评论您的验证在期望旧领域的模型上有。

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

这是原子,并且不需要模型上的节省。

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

如前所述,我认为有一个更好的办法,因此,如果任何人有一些提示,请分享。谢谢!

+0

只是一个问题。任何机会你的光标超时大数据集? – 2012-02-24 00:09:28

+0

是的,我认为蒙戈的默认光标超时时间为10分钟,可发生肯定的。如果你可以斟酌地写它(检查amount2是否为零)并且多次运行,这可能会起作用。绝对看起来比它应该是困难的。 – 2012-08-16 06:08:04

+0

更新,我大概应该用这样的:https://github.com/nviennot/mongoid_lazy_migration看起来比我做了什么 – 2012-08-16 06:38:14

相关问题