9

モデルを最初に所属先と多数の関連付けで構築した後、組み込みインと多数の関連付けに移行する必要があることに気付いた場合、何千ものレコードを無効にすることなくこれを行うにはどうすればよいでしょうか? 何らかの方法でそれらを移行する必要があります。

4

4 に答える 4

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 モデルを削除して、変更を完了できます。

  • これは単なる提案です。本番環境で試す前に、開発環境でこれを試してください。ですから、私の提案には何か問題があるのではないかと思います。
于 2013-04-11T07:53:47.677 に答える
1

10gen には、データ モデリングに関する有用な記事がいくつかあります。

埋め込みに関しては、MongoDB には 2 つの制限があることに注意してください。

  • ドキュメントのサイズ制限は 16MB です。これは、オブジェクト ID を埋め込んだだけでも、埋め込まれたドキュメントの最大数を意味します。
  • トップレベルからすべての埋め込みドキュメントを検索したい場合は、埋め込みではなく、代わりに参照ドキュメントを使用してください!
于 2013-04-19T03:27:30.720 に答える
0

私ははるかに短い簡潔な答えを持っています:

同じモデルがあると仮定しましょう:

#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]機能します。それらを削除するために何もしていません。

これで、リレーショナルから組み込みへの簡単な移行が完了しました

于 2015-01-14T15:07:49.913 に答える