运行时更改模型与mongodb/mongoid

BBJ*_*BJ3 9 ruby migration mongodb nosql mongoid

我要在mongoid模型中添加几个字段,我知道没有MongoDB的迁移但是如果我继续而不删除数据库,使轨道完全"重新生成"数据库,它不显示或使用新字段一点都没有!

什么是最好的方式去这里?有什么比放弃/重新打开mongodb更软的东西吗?

在此先感谢luca

asa*_*aki 11

通常,应该可以在运行时使用新字段更新旧文档.MongoDB中不需要迁移.

您可能希望编写rake任务以使用新字段和默认值更新旧文档.

您可以通过检查默认值为零的新字段来查找这些文档.


更新

简约风格:

如果使用默认值定义新字段,则只要设置新值,就应始终使用此值:

应用程序/模型/ my_model.rb

class MyModel
  include Mongoid::Document
  field :name, type: String
  field :data, type: String
  # NEW FIELD
  field :note, type: String, default: "no note given so far!"
end
Run Code Online (Sandbox Code Playgroud)

如果您查询数据库,则应在扩展名之前获取没有此字段的文档的默认值:

(rails console)

MyModel.first
#=> #<MyModel …other fields…, note: "no note given so far!">
Run Code Online (Sandbox Code Playgroud)

我在Ruby 1.9.2上用一个新的rails堆栈和一个当前的mongoid测试了它 - 也应该与其他堆栈一起使用.

更复杂/复杂的风格:

如果您没有设置默认值,则此新字段将为nil.

应用程序/模型/ my_model.rb

class MyModel
  include Mongoid::Document
  field :name, type: String
  field :data, type: String
  # NEW FIELD
  field :note, type: String
end
Run Code Online (Sandbox Code Playgroud)

(rails console)

MyModel.first
#=> #<MyModel …other fields…, note: nil>
Run Code Online (Sandbox Code Playgroud)

然后,您可以设置rake任务和迁移文件,如下例所示:

LIB /任务/ my_model_migration.rake:

namespace :mymodel do
  desc "MyModel migration task"
  task :migrate => :environment do
    require "./db/migrate.rb"
  end
end
Run Code Online (Sandbox Code Playgroud)

DB/migrate.rb:

olds = MyModel.where(note: nil)
# Enumerator of documents without a valid :note field (= nil)
olds.each do |doc|
  doc.note = "(migration) no note given yet"
  # or whatever your desired default value should be
  doc.save! rescue puts "Could not modify doc #{doc.id}/#{doc.name}"
  # the rescue is only a failsafe statement if something goes wrong
end
Run Code Online (Sandbox Code Playgroud)

运行此迁移rake mymodel:migrate.

这只是一个起点,您可以将其扩展为完整的mongoid迁移引擎.

task :migrate => :environment do …是必要的,否则耙不会加载模型.