モデルを最初に所属先と多数の関連付けで構築した後、組み込みインと多数の関連付けに移行する必要があることに気付いた場合、何千ものレコードを無効にすることなくこれを行うにはどうすればよいでしょうか? 何らかの方法でそれらを移行する必要があります。
4 に答える
私の解決策が正しいかどうかはわかりません。これは、達成しようとする可能性があるものです。
モデルがあるとします-このように
#User Model
class User
include Mongoid::Document
has_many :books
end
#Book Model
class Book
include Mongoid::Document
field :title
belongs_to :user
end
最初のステップでは、上記の Book モデルに似た別のモデルを作成しますが、参照されるのではなく埋め込まれています。
#EmbedBook Model
class EmbedBook
include Mongoid::Document
field :title
embedded_in :user
end
#User Model (Update with EmbedBook Model)
class User
include Mongoid::Document
embeds_many :embed_books
has_many :books
end
次に、上記の例のように Mongoid Migration を作成します
class ReferenceToEmbed < Mongoid::Migration
def up
User.all.each do |user|
user.books.each do |book|
embed_book = user.embed_books.new
embed_book.title = book.title
embed_book.save
book.destroy
end
end
end
def down
# I am not so sure How to reverse this migration so I am skipping it here
end
end
移行を実行した後。ここから、参考書が埋め込まれていることがわかりますが、埋め込まれたモデルの名前は EmbedBook で、モデルブックはまだそこにあります
したがって、次のステップは、モデル ブックを埋め込みとして作成することです。
class Book
include Mongoid::Document
embedded_in :user
field :title
end
class User
include Mongoid::Document
embeds_many :books
embeds_many :embed_books
end
次は、embedbook タイプを book タイプに移行します。
class EmbedBookToBook < Mongoid::Migration
def up
User.all.each do |user|
user.embed_books.each do |embed_book|
book = user.books.new
book.title = embed_book.title
book.save
embed_book.destroy
end
end
def down
# I am skipping this portion. Since I am not so sure how to migrate back.
end
end
Book が参照から埋め込みに変更された場合。EmbedBook モデルを削除して、変更を完了できます。
- これは単なる提案です。本番環境で試す前に、開発環境でこれを試してください。ですから、私の提案には何か問題があるのではないかと思います。
10gen には、データ モデリングに関する有用な記事がいくつかあります。
埋め込みに関しては、MongoDB には 2 つの制限があることに注意してください。
- ドキュメントのサイズ制限は 16MB です。これは、オブジェクト ID を埋め込んだだけでも、埋め込まれたドキュメントの最大数を意味します。
- トップレベルからすべての埋め込みドキュメントを検索したい場合は、埋め込みではなく、代わりに参照ドキュメントを使用してください!
私ははるかに短い簡潔な答えを持っています:
同じモデルがあると仮定しましょう:
#User Model
class User
include Mongoid::Document
has_many :books
end
#Book Model
class Book
include Mongoid::Document
field :title
belongs_to :user
end
したがって、埋め込みに変更します。
#User Model
class User
include Mongoid::Document
embeds_many :books
end
#Book Model
class Book
include Mongoid::Document
field :title
embedded_in :user
end
そして、次のようなモンゴイド マイグレーションを生成します。
class EmbedBooks < Mongoid::Migration
@@attributes_to_migrate = [:title]
def self.up
Book.unscoped.where(:user_id.ne => nil).all.each do |book|
user = User.find book[:user_id]
if user
attrs = book.attributes.slice(*@@attributes_to_migrate)
user.books.create! attrs
end
end
end
def self.down
User.unscoped.all.each do |user|
user.books.each do |book|
attrs = @@attributes_to_migrate.reduce({}) do |sym,attr|
sym[attr] = book[attr]
sym
end
attrs[:user] = user
Book.find_or_create_by(**attrs)
end
end
end
end
これは、クラス レベルからクエリを実行すると、トップ レベルのコレクション (関係を変更してもまだ存在する) を探しているためbook[:user_id]
機能します。それらを削除するために何もしていません。
これで、リレーショナルから組み込みへの簡単な移行が完了しました