2013-04-24 7 views
6

Mam sytuację, w której mam dokument nadrzędny i chcę mieć dwa różne typy dokumentów osadzonych: jeden jako rodzic, a drugi jako dziecko z opcjonalnym rodzicem. NpMongoid: Jak wdrożyć relację między dokumentami osadzonymi?

class ParentDoc 
    include Mongoid::Document 
    embeds_many :special_docs 
    embeds_many :special_doc_groupings 
end 

class SpecialDoc 
    include Mongoid::Document 
    embedded_in :parent_doc 
    belongs_to :special_doc_groupings 
end 

class SpecialDocGrouping 
    include Mongoid::Document 
    embedded_in :parent_doc 
    has_many :special_docs 
end 

W tym przykładzie SpecialDocs i SpecialDocGroupings może istnieć bez związku, lub ewentualnie mogą mieć relacji nadrzędny-podrzędny.

Jednak jest to nieprawidłowy stowarzyszenie Mongoid ponieważ ten błąd:

Mongoid::Errors::MixedRelations:

Problem: Referencing a(n) SpecialDoc document from the SpecialDocGrouping document via a relational association is not allowed since the SpecialDoc is embedded.

Summary: In order to properly access a(n) SpecialDoc from SpecialDocGrouping the reference would need to go through the root document of SpecialDoc. In a simple case this would require Mongoid to store an extra foreign key for the root, in more complex cases where SpecialDoc is multiple levels deep a key would need to be stored for each parent up the hierarchy.

Resolution: Consider not embedding SpecialDoc, or do the key storage and access in a custom manner in the application code.

nie widzę niczego złego w rodzaju stowarzyszenia, które staram się tworzyć, oprócz faktu, że jest to nie obsługiwane przez Mongoid.

Jak mogę samodzielnie wdrożyć ten typ powiązania?

+0

Yaa prawej stronie nie można określić tego typu stowarzyszenie w mongoid w odniesieniu do Twojego pytania 'wdrożyć tego typu stowarzyszenia siebie?' Dobrze słyszeliście [przedłużyć] (http://guides.rubyonrails.org/association_basics.html#extend) w stowarzyszeniu activerecord dobrze możesz zaimplementować coś podobnego lub użyć rozszerzenia, jeśli mongoid również obsługuje coś w tym rodzaju (sprawdzę to i dam ci znać) Pozdrowienia – Viren

Odpowiedz

10

Powiązanie jest nieprawidłowe, ponieważ gdy odwołujesz się do modelu osadzonego, Mongoid nie przechowuje klucza nadrzędnego jako klucza obcego. Oznacza to, że jeśli masz:

Class Parent   
    embeds_many :children 
end 

Class Child 
    embedded_in :parent 
end 

nie można odwołać dokument podrzędny przechowującą tylko jego klucz obcy, ale trzeba przechowywać wszystkie klucze rodziców aż do korzenia. W tym przypadku root jest reprezentowany przez pierwszego rodzica i trzeba przechowywać 2 klucze.

Można to zrobić ręcznie i utworzyć ten typ powiązania bez problemu.

Twoja sprawa jest nieco inna (i łatwiejsza), ponieważ chcesz utworzyć powiązanie między dwoma modelami osadzonymi w tym samym rodzica. Oznacza to teoretycznie, że nie trzeba przechowywać klucza nadrzędnego, ponieważ modele mają ten sam katalog główny. Mongoid nie obsługuje tego scenariusza, więc musisz ręcznie utworzyć reguły asocjacyjne i metody.

Class Bar 
    embeds_many :beers 
    embeds_many :glasses 
end 

Class Beer 
    embedded_in :bar 
    # Manual has_many :glasses association 
    def parent 
    self.bar 
    end 

    def glasses 
    parent.glasses.where(:beer_id => self.id) 
    end 

end 

Class Glass 
    embedded_in :bar 
    # Manual belongs_to :beer association 
    field :beer_id, type: Moped::BSON::ObjectId 
    def parent 
     self.bar 
    end 

    def beer 
     parent.beers.find(self.beer_id) 
    end 
end 

(kod nie jest testowany)

+1

Nie bardzo rozumiem twoje wyjaśnienie, ale twoje rozwiązanie jest prawie identyczne z tym, co wymyśliłem. Lubię również twoje przykładowe nazwiska. =] – Andrew

+0

Jak zrobiłbyś to w Mongoid, jeśli dokumenty osadzone, które chcesz powiązać, mają różne dokumenty nadrzędne? – elsurudo