Mongoid: How to implement the relationship between embedded documents?

I have a situation where I have a parent document, and I want to have two different types of embedded documents: one as a parent, and the other as a child with an additional parent. For instance:

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 

In this example, SpecialDocs and SpecialDocGroupings may exist without a relationship, or may optionally have a parent-child relationship.

However, this is an invalid Mongoid association because we get this error:

Mongoid :: Errors :: MixedRelations:

Problem: A reference to the (n) SpecialDoc document from the SpecialDocGrouping document through a relational association is not allowed because SpecialDoc is built-in.

Summary: For proper access to (n) SpecialDoc from SpecialDocGrouping, the link must go through the root document of SpecialDoc. In the simple case, this will require Mongoid to store an additional foreign key for the root, in more complex cases when SpecialDoc has several levels, the key must be stored for each parent in a hierarchy.

Resolution: Think about not embedding SpecialDoc, as well as storing and storing the key in user mode in the application code.

I do not see anything wrong with the type of association I am trying to create, except that it is not supported by Mongoid.

How can I implement this type of association on my own?

+6
source share
1 answer

The relationship is invalid because when you reference the built-in model, Mongoid does not save the parent key as a foreign key. This means that if you have:

 Class Parent embeds_many :children end Class Child embedded_in :parent end 

You cannot reference a child document storing only its foreign key, but you need to save all the keys of the parents until you reach the root . In this case, the root is represented by the first parent, and you need to save 2 keys.

You can do this manually and create such an association without any problems.

Your case is slightly different (and simpler) because you want to create a relationship between two models embedded in the same parent. This means that theoretically you do not need to store the parent key, because the models have the same root. Mongoid cannot handle this scenario, so you need to manually create your association rules and methods.

 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 

(code not verified)

+10
source

Source: https://habr.com/ru/post/943579/


All Articles