Динамическая изменяющаяся модель с mongodb / mongoid - PullRequest
9 голосов
/ 17 июля 2011

Мне нужно добавить несколько полей в модели mongoid, я знаю, что с MongoDB не происходит миграции, но если я продолжу, не сбрасывая БД, делая рельсы для «полной регенерации» БД, она не будет отображаться или использоватьсяновые поля вообще!

Какой лучший путь сюда?Есть ли что-нибудь более мягкое, чем drop / reongen mongodb?

Заранее спасибо luca

Ответы [ 3 ]

11 голосов
/ 17 июля 2011

В общем случае должна быть возможность обновить старые документы новыми полями во время выполнения. В MongoDB нет необходимости в миграции.

Возможно, вы захотите написать грабли для обновления старых документов новыми полями и значениями по умолчанию.

Вы можете узнать эти документы, проверив те новые поля, которые по умолчанию имеют значение nil.


Обновление

Простой стиль:

Если вы определяете новое поле со значением по умолчанию, это значение всегда должно использоваться, пока вы устанавливаете новое:

приложение / модели / 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

Если вы запрашиваете базу данных, вы должны получить значение по умолчанию для документов, которые не имеют этого поля до вашего расширения:

(рельсы консольные)

MyModel.first
#=> #<MyModel …other fields…, note: "no note given so far!">

Я протестировал это со свежим стеком рельсов с текущим монгоидом на Ruby 1.9.2 - должно работать и с другими стеками.

Более сложный / сложный стиль:

Если вы не установили значение по умолчанию, вы получите ноль для этого нового поля.

приложение / модели / my_model.rb

class MyModel
  include Mongoid::Document
  field :name, type: String
  field :data, type: String
  # NEW FIELD
  field :note, type: String
end

(рельсы консольные)

MyModel.first
#=> #<MyModel …other fields…, note: nil>

Затем вы можете настроить задачу rake и файл миграции, как в этом примере:

Библиотека / Задачи / my_model_migration.rake:

namespace :mymodel do
  desc "MyModel migration task"
  task :migrate => :environment do
    require "./db/migrate.rb"
  end
end

дб / 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

Запустите эту миграцию с rake mymodel:migrate.

Это только отправная точка, и вы можете расширить ее до механизма полной миграции mongoid.

Необходим task :migrate => :environment do …, иначе грабли не будут загружать модели.

4 голосов
/ 22 октября 2012

Немного смешно говорить, что вам не нужны миграции с mongodb или mongoid.Любое сложное приложение должно время от времени подвергаться рефакторингу, что может означать извлечение полей из разрозненных документов в новое.

Запись однократных задач является менее удобным и подверженным ошибкам, чем миграция в составе сценария развертывания, поэтому он всегда запускается в любой среде.

https://github.com/adacosta/mongoid_rails_migrations приноситМиграции в стиле AR в mongoid.

Они могут понадобиться вам реже, но они наверняка понадобятся по мере роста приложения.

1 голос
/ 08 января 2012

Ниже приведен хороший пример кода для скрипта переноса данных с mongoid и драйвером ruby ​​mongo, который используется, когда обновленная модель больше не соответствует производственным данным.

http://pivotallabs.com/users/lee/blog/articles/1548-mongoid-migrations-using-the-mongo-driver

Iпоэтому мы бы прекратили использовать "нет миграций с монгоидом" в качестве лозунга.Это приведет людей к MongoDB по неправильным причинам, и это только частично верно.Нет схемы, правда, но данные все еще нужно поддерживать, что IMO сложнее с MongoDB, чем RDBM.Есть и другие веские причины для выбора MongoDB, и это зависит от вашей проблемы.

...