【问题标题】:Rails database setup PolymorphismRails 数据库设置多态性
【发布时间】:2017-12-01 19:41:10
【问题描述】:

我们必须创建一个请求系统,该系统将包含大约 10 种不同类型的请求。所有这些请求都属于我们应用程序的“会计”方面。因此,我们称它们为“会计请求”。

所有请求可能只共享几列,每个请求最多单独包含 20 列。

当我们开始必须执行非常复杂的连接或查询时,我们开始怀疑为每种请求类型分别设置表是否在速度方面是否实用,例如,将所有请求类型提取到单个表中然后对其进行排序.

也许只使用单表继承会更容易,因为它有一个类型列,我们将使用一个表来存储所有 10 种记帐请求类型。

您如何看待将 STI 用于如此多的多态关联和需求?

基本上,它会有这样的模型:

AccountingRequest
BillingRequest < AccountingRequest
CheckRequest < AccountingRequest
CancellationRequest < AccountingRequest

每个子类大约有 10 多个字段。


目前正在阅读有关多表继承here 的信息。在这种情况下,这似乎是符合我要求的解决方案。不过还不确定。

【问题讨论】:

  • 请解释反对票,而不仅仅是反对票。在不知道这些谴责背后的原因的情况下看到这一点很烦人。

标签: ruby-on-rails ruby-on-rails-3 database-design relational-database single-table-inheritance


【解决方案1】:

如果您的模型都具有相同的属性,则 STI 非常适合。

但是,如果您的子类开始具有特定于它们的属性并且不适用于其他属性,那么 STI 可能会导致大量空列。在这种情况下,我通常更喜欢使用多态关联。

railscast 这一集很好地说明了两者之间的差异

【讨论】:

    【解决方案2】:

    您可以在这种情况下使用 STI。但是制作 STI 需要将所有列放在一个表中,这不是好主意。表格的字段数会很大。

    我认为你应该分成如下两个表...

    1. 请求:请求表将是保存请求类型信息的多态表。

    2. RequestItem:请求项表会将所有20个字段记录保存到表中,并具有请求表的外键。请求项表将在数据库中包含两个字段,称为键和值。

    【讨论】:

    • 我自己拒绝键值方法的原因是它很难进行有效的查询、添加约束/验证以及使用正确的数据类型。
    【解决方案3】:

    听起来可行。

    当我对此进行研究时,我发现广泛使用值对象有助于控制某些属性对某些类型的不适用性。

    就我而言,我有一些产品类型,例如,其中一些没有特定的尺寸。在这些情况下,我在适当的地方使用 Null 对象来指示“不适用”。

    编辑:我还发现composer_of语法非常方便:https://apidock.com/rails/ActiveRecord/Aggregations/ClassMethods/composed_of

    【讨论】:

      【解决方案4】:

      现在我在这种情况下使用了一些 NoSQL。 Postgresql's JSONB 类型允许存储多级红宝石哈希。它还提供了丰富的功能:数据库级约束、索引和查询运算符。

      因此,通用属性以标准方式和特定于子级的方式存储 - 在 jsonb 中。然后您可以在此之上使用您需要的任何东西:STI、值对象模式、序列化或只是为每个孩子创建范围。我更喜欢最后一个 - 我的模型很薄,大多数约束是数据库级别的,所有业务逻辑都在服务类中。

      优点:

      1. 在需要添加更多子类型时避免在大表上使用 alter table
      2. 保持查询高效
      3. 防止存储和选择不必要的列
      4. 开箱即用的 JSON API 序列化

      缺点:

      1. 有点无模式
      2. 供应商锁定

      【讨论】:

        猜你喜欢
        • 2014-04-28
        • 1970-01-01
        • 2015-01-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-07-11
        • 2012-06-28
        • 1970-01-01
        相关资源
        最近更新 更多