我正在设计一个具有一些特定规则的数据库结构,并且试图定义一个合适的数据模型,基本上是一种适合那些规则的数据模型。
共有3个实体:
subgroups
,items
...)group
,items
...)enabled
,description
...)这些实体具有关系:
SubGroup
属于一个Group
(一个Group
拥有几个SubGroup
)Item
可以属于Group
或SubGroup
(一次只能属于一个)还有一些特殊规则:
Item
的{{1}}继承给所有相关的Group
SubGroup
从其Item
继承的SubGroup
可以被覆盖(我称它为继承,因为那样子会被父辈继承并可以按原样覆盖或使用)
Group
字段,因为在某些情况下我们可能想禁用通过继承获得的项此示例保持简单,但实际情况有点复杂,可以有更多的“ SubGroup”级别,例如“ SubSubGroup”,因此结构也应适当地处理这些 >
起初,我想到了一种传统的关系:
如果不是针对那些“特殊规则”,这将很好地工作。因为这种结构无法覆盖继承的enabled
。
因此,我也做了第二次尝试。
我通过使用一种“代理”表进行了另一种设计尝试,该表基本上是一个名为Item
的nn关系表(该名称太可怕了,但我没有发现更好的方法)除了现有实体(ItemOverride
,Group
和SubGroup
)
实体Item
包含以下字段:
ItemOverride
或Group
)SubGroup
相关的ID)实体EntityType
扩展了ItemOverride
实体,使其包含相同的字段,从而可以覆盖任何字段。
Item
表中的内容示例:
ItemsOverride
此设计似乎提供了适当的结构,我添加了+--------+------------+----------+-----------------+---------------------+
| ItemId | EntityType | EntityId | Enabled | OverriddenHeight |
+--------+------------+----------+-----------------+---------------------+
| 1 | group | 1 | true | null |
| 2 | group | 2 | true | 20 |
| 3 | subgroup | 1 | false | |
+--------+------------+----------+-----------------+---------------------+
和OverriddenWidth
来说明覆盖的字段。关键是只存储被覆盖的内容,而将其他值保留为空,以便它依赖于实际的OverriddenHeight
实体来获取这些值。
但是,我觉得它变得比需要的要复杂得多,我想知道是否有更好的方法来解决这个问题。
使用此结构可以看到一些潜在的痛点:
Item
继承了ItemOverride
,则必须在Item
表中设置不允许“ null”的字段,这将浪费空间,重复的内容和其他问题,因为这将使得很难从继承的内容中看到真正被覆盖的内容ItemOverride
和ItemOverride
之间没有继承,则Item
模型将“无用”地复制其大部分字段,并且必须完成添加/更新/删除字段在两个表而不是一个因此,我不知道此设计是否“足够好”,或者可以改进/简化。如果您知道这样的继承/重写需求,我很想涉足类似的项目。
我的第二次尝试似乎符合我的需求,这是我不得不立即开始使用的,因为我不知道如何改善它。
此设计没有数据冗余,但是当ItemOverride
继承SubGroup
的{{1}}时,如何处理数据覆盖仍然不清楚。如果将覆盖范围限制为Group
字段,那么这很容易,但是如果有很多字段,则维护起来会有些复杂。使用模型/表继承也可能使事情复杂化,因为我们不想存储非覆盖值,因此希望允许Item
表中的所有字段使用required
(这可能是不可能的)如果我们在null
实体中强制执行不可为空的规则,因为它们也会同样应用于ItemOverride
)
为了记录,我使用的是Django。它强大的内部ORM优雅地处理Item
和DynamicRelationship,它们允许使用模型的字段引用动态实体。 (我将其称为ItemOverride
),这就是第二次尝试设计采用这种方式设计的原因之一(更容易依赖于我的框架提供的功能)。但是我对完全不同的可能性/选择持开放态度。