We'll respond shortly.
When first starting out with mongodb, it’s easy to make the wrong decision on whether to embed a document or not. Even if you made the correct decision at that moment, changing requirements may force you into a migration. So how do you migrate existing data when transitioning from a standalone document to an embedded document? This is what I came up with.
class User include Mongoid::Document field :name references_many :sales end class Sale include Mongoid::Document field :price, :type => Integer referenced_in :user end
class User include Mongoid::Document field :name embeds_many :sales end class Sale include Mongoid::Document field :price, :type => Integer embedded_in :user, :inverse_of => :sales end
class EmbedSalesInUsers < Mongoid::Migration def self.up # pull your existing data into memory # consider batching for large data sets # Note that you must call query methods on the object you are migrating # for this method to work (i.e. you can not pull via User#sales) sales_attributes = while_stand_alone_doc(Sale) do Sale.all.map(&:attributes) end # now when you save your data, your fields will be embedded sales_attributes.each do |attributes| user = User.find(attributes[:user_id]) user.sales << Sale.new(:price => attributes[:price]) end # remove all the documents from the original collection while_stand_alone_doc(Sale) do Sale.destroy_all end end def self.while_stand_alone_doc(klass) # by changing the Mongoid::Document.embedded you can temporarily # modify which collection Mongoid looks to for your model's data store begin klass.embedded = false yield ensure klass.embedded = true end end end
There are a couple things to note here.