【问题标题】:Self referential embedded documents using Mongoid使用 Mongoid 的自引用嵌入文档
【发布时间】:2013-03-29 13:18:12
【问题描述】:

假设我有一个名为 Foo 的 mongoid 模型,它嵌入了许多 Bar。

class Foo
    ...
    embeds_many :bar
    ...
end

class Bar
    ...
    embedded_in :foo
    ...
end

我想创建一个 Bar 链接到它自己的关系。该关系将始终涉及嵌入在同一个 Foo 文档中的两个文档。在调用关系时,我似乎无法做到这一点而没有返回 nil。我试过了

belongs_to :discovered_by, :class_name => 'Bar'

还有

has_one :discovered_by, :class_name => 'Bar'

虽然在 Bar 文档中设置了 found_by id,并在我尝试执行以下操作时指向另一个 Bar 文档,但我得到 nil(假设第一个 Foo 的第一个 Bar 设置了 found_by_id)

Foo.first.bars.first.discovered_by

尽管文档设置了 id,这将始终返回 nil。知道为什么会这样吗?感谢您的帮助。

【问题讨论】:

    标签: ruby mongodb mongoid


    【解决方案1】:

    cannot have references to embedded models - 即使它们都嵌入在同一个文档中。如果你正确配置了关系

    belongs_to :discovered_by, :class_name => 'Bar', inverse_of: :discovered
    has_one :discovered, :class_name => 'Bar', inverse_of: :discovered_by
    

    Mongoid 将引发Mongoid::Errors::MixedRelations 异常。也许您可以重新考虑嵌入这些对象是否仍然是最佳选择。一种解决方法是仅存储 id 并查询父对象:

    class Bar
        include Mongoid::Document
        embedded_in :foo
        field :discovered_by_id, type: Moped::BSON::ObjectId
    
        def discovered_by
          foo.bars.find(discovered_by_id) if discovered_by_id
        end
    
        def discovered_by=(bar)
          self.discovered_by_id = bar.id
        end
    end
    

    【讨论】:

    • 我想我必须按照您在解决方案中的建议存储 id。不理想,但它符合我的目的。话虽如此,您关于重新考虑嵌入式文档的评论很有趣。将嵌入在同一父文档中的两个文档视为相关的做事是否违反“mongo 方式”?我想这与 Mongoid 的实现是一致的。
    • 是的,通常引用嵌入式文档是个坏主意。部分从技术角度(使用关系的对象必须知道嵌入模型的每一层的父对象)和设计角度(嵌入对象只能通过其父对象访问)。但是,您的示例有点极端:您肯定知道您所指的记录的父对象 (foo)。我可能会采用解决方法 - 唯一的缺点是您不能使用标准的 belongs_tohas_one 助手。
    猜你喜欢
    • 2011-04-22
    • 1970-01-01
    • 1970-01-01
    • 2011-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多