2013-04-09 17 views

Odpowiedz

4

nie jestem więc pewien, że moje rozwiązanie jest słuszne czy nie. To jest coś, co możesz spróbować osiągnąć.

Załóżmy, że masz modeli - jak to

#User Model 
class User 
    include Mongoid::Document 
    has_many :books 
end 

#Book Model 
class Book 
    include Mongoid::Document 
    field :title 
    belongs_to :user 
end 

W pierwszym etapie będę stworzyć kolejny model, który jest podobny do modelu Book powyżej, ale jest osadzony zamiast odwoływać.

#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 

Następnie utwórz Mongoid Migracja z czymś takim na powyższym przykładzie

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 

Po przeprowadzeniu migracji. Z tego miejsca widać, że książki referencyjne są osadzone, ale nazwa wbudowanego modelu to EmbedBook, a model Book nadal istnieje.

Zatem następnym krokiem będzie stworzenie książki modelowej jako osadzonej.

class Book 
    include Mongoid::Document 
    embedded_in :user 
    field :title 
end 

class User 
    include Mongoid::Document 
    embeds_many :books 
    embeds_many :embed_books 
end 

Więc następnym będzie migrować typ embedbook do Book Type

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 

Teraz Jeśli widzisz Book zmienia się odwoływać do osadzonych. Możesz usunąć model EmbedBook, aby zmiany zostały zakończone.

  • To tylko sugestia. Wypróbuj to w swoim rozwoju przed próbą produkcji. Ponieważ uważam, że w mojej sugestii może być coś nie tak.
+0

Dzięki, wziąłem twoją sugestię i stworzył kilka zadań rake do migracji. – Dean

1

10gen ma kilka artykułów na temat modelowania danych, które mogłyby być użyteczne:

Pamiętaj, że istnieją dwa ograniczenia MongoDB, jeśli chodzi o osadzanie:

  • wielkość limitu dokument jest 16MB - oznacza to maksymalną liczbę osadzonych dokumentów, nawet jeśli tylko osadzić ich celem ID
  • jeśli kiedykolwiek chcesz wyszukać we wszystkich osadzonych dokumentów z najwyższym poziomie, to nie osadzać, ale zamiast używać odwołuje dokumentów!
1

Spróbuj kroki:

  1. W User modelu opuścić has_many :books relację i dodaj osadzony relację z inną nazwą, aby nie przesłonić metodę books .

    class User 
         include Mongoid::Document 
    
         has_many :books 
         embeds_many :embedded_books, :class_name => "Book" 
        end 
    

    Teraz, jeśli wywołać metodę z pomocą User instancji mongoid embedded_books powinien powrócić pustą tablicę.

  2. bez dodawania żadnego wbudowanego stosunku do Book modelu napisać własny skrypt migracji:

    class Book 
        include Mongoid::Document 
    
        field :title, type: String 
        field :price, type: Integer 
        belongs_to :user 
    
        def self.migrate 
         attributes_to_migrate = ["title","price"] # Use strings not symbols, 
                   # we keep only what we need. 
                   # We skip :user_id field because 
                   # is a field related to belongs_to association. 
         Book.all.each do |book| 
         attrs = book.attributes.slice(*attributes_to_migrate) 
         user = book.user // through belong_to association 
         user.embedded_book.create!(attrs) 
         end 
        end 
    end 
    

    Wywołanie Book.migrate trzeba mieć wszystkie książki skopiowane wewnątrz każdego użytkownika, który był związany z belongs_to relacji.

  3. Teraz możesz usunąć relacje has_many i belongs_to, a następnie w końcu przejść do czystego rozwiązania osadzonego.

    class User 
        include Mongoid::Document 
    
        embeds_many :books 
    end 
    
    class Book 
        include Mongoid::Document 
    
        field :title, type: String 
        field :price, type: Integer 
        embedded_in :user 
    end 
    

Nie testowałem tego rozwiązania, ale teoretycznie powinny działać, daj mi znać.

0

Mam dużo krótszy odpowiedź zwięzłą:

Załóżmy, że masz te same modele:

#User Model 
class User 
    include Mongoid::Document 
    has_many :books 
end 

#Book Model 
class Book 
    include Mongoid::Document 
    field :title 
    belongs_to :user 
end 

więc zmienić go na innych witrynach:

#User Model 
class User 
    include Mongoid::Document 
    embeds_many :books 
end 

#Book Model 
class Book 
    include Mongoid::Document 
    field :title 
    embedded_in :user 
end 

i wygenerować mongoid migracji tak:

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 

Działa to, ponieważ podczas zapytania z poziomu klasy, szuka kolekcji najwyższego poziomu (która nadal istnieje, nawet jeśli zmienisz swoje relacje), a book[:user_id] jest sztuczką, aby uzyskać dostęp do atrybutu dokumentu, a nie automatycznie generowane metody, które również istnieją ponieważ nie zrobiłeś nic, aby je usunąć.

A więc masz to, prosta migracja z relacji do wbudowanego

Powiązane problemy