7

我有一种情况,我有一个父文档,并且我想要两种不同类型的嵌入文档:一种作为父文档,另一种作为具有可选父文档的子文档。例如:

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

在此示例中,SpecialDocs 和 SpecialDocGroupings 可以不存在关系,也可以有父子关系。

然而,这是一个无效的 Mongoid 关联,因为我们得到了这个错误:

Mongoid::Errors::MixedRelations:

问题:由于嵌入了 SpecialDoc,因此不允许通过关系关联从 SpecialDocGrouping 文档中引用 (n) SpecialDoc 文档。

摘要:为了从 SpecialDocGrouping 正确访问一个(n)SpecialDoc,引用需要通过 SpecialDoc 的根文档。在一个简单的情况下,这将需要 Mongoid 为根存储一个额外的外键,在更复杂的情况下,SpecialDoc 是多个级别的深度,则需要为层次结构中的每个父级存储一个键。

解决方案:考虑不嵌入 SpecialDoc,或者在应用程序代码中以自定义方式进行密钥存储和访问。

除了 Mongoid 不支持它之外,我认为我尝试创建的关联类型没有任何问题。

我如何自己实现这种类型的关联?

4

1 回答 1

10

该关联无效,因为当您引用嵌入式模型时,Mongoid 不会将父键存储为外键。这意味着如果您有:

Class Parent        
   embeds_many :children
end 

Class Child
   embedded_in :parent
end

您不能引用仅存储其外键的子文档,但您需要存储所有父键,直到您到达 root。在这种情况下,根由第一个父级表示,您需要存储 2 个密钥。

您可以手动完成此操作,并毫无问题地创建这种类型的关联。

您的情况有点不同(并且更容易),因为您想创建嵌入在同一父项中的两个模型之间的关联。这意味着理论上您不需要存储父键,因为模型共享相同的根。Mongoid 不处理这种情况,因此您需要手动创建关联规则和方法。

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

(代码未经测试)

于 2013-04-26T13:49:21.867 回答