【问题标题】:Mongoid, how to keep relations in sync for common parent model?Mongoid,如何使公共父模型的关系保持同步?
【发布时间】:2013-09-15 20:44:31
【问题描述】:

我有三个模型:

Agency
has_many :owners
has_many :properties

Owner
belongs_to :agency
has_many :properties

Property
belongs_to :owner
belongs_to :agency

agency.properties 关系应该引用所有所有者拥有的所有属性,但是当我在所有者内部创建属性时,agency.properties 关系不会创建。我希望这种关系能够自动实现,并在所有者或属性被删除时被删除。

如何使用 mongoid 实现这种行为?

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 mongoid ruby-on-rails-4 mongoid3


    【解决方案1】:

    你也可以这样写:

    Agency
    has_many :owners
    
    Owner
    belongs_to :agency
    has_many :properties
    
    Property
    belongs_to :owner
    

    然后在你的代理模型中添加一个实例方法:

    def properties
     owners.map(&:properties).flatten.uniq
    end
    

    但是,此方法将查询您的数据库以检索所有者,然后为每个所有者再次查询您的数据库一次以检索每个所有者的属性。

    希望这会有所帮助。

    编辑

    还有另一种解决方案,这意味着只有 2 个查询:

    def properties
     Property.where({:owner_id.in => owner_ids})
    end
    

    优点

    它只使用两个查询。

    它返回一个 Mongoid Criteria(之前的解决方案返回一个数组)。因此,您可以链接范围等(即 my_agency.properties.sold #如果您已定义销售范围)

    缺点

    这段代码似乎不太可读。

    此外,它的可维护性较差。如果您更改 Owner-Property 关系中的外键,则应更新此方法 (Property.where({:foreign_key...}) 或更改所有者拥有许多属性的方式。只要第一个选项仍然有效每个所有者属性都可以通过实例方法 some_owner.properties 找到。

    【讨论】:

    • 这确实很漂亮,但引入了一个 n+1 问题。
    • @JúlioTurollaRibeiro。我认为我们应该首先问:“一个机构可能有多少个所有者?一万或一万个?查询速度有多快?”然后:“代理和财产之间是否存在真正的关系?或者代理拥有财产只是因为他们拥有所有者,而所有者又拥有财产?”随着您的应用程序的增长,保持所有关系同步的难易程度如何??
    • @JúlioTurollaRibeiro。我用just-2-queries 解决方案编辑了答案;但它引入了一些关于代码维护的其他问题。问候
    【解决方案2】:

    由于这是一个非常具体的用例,因此无法使用“开箱即用”的 mongoid 来“自动”执行此操作。我建议你有一些 before_save 钩子,这将保证你的关系状态。您还可以根据您的用例,Property 可以是 Owner 和 Agency 内部的非规范化(嵌入)对象。

    【讨论】:

    • 好的。你认为我这样做会不会出现相关的性能问题?
    • 是的,如果你有大量的集合,必须保持这些 has_many 同步会影响写入。另请记住,Mongodb 没有跨多个集合的原子事务,因此您可能会有不一致的数据。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多