database - 具有多个关系和继承的实体的灵活数据库结构
问题描述
我正在设计一个具有一些特定规则的数据库结构,并且我正在尝试定义一个合适的数据模型,基本上是一个符合这些规则的模型。
有3个实体:
- 组(字段:
subgroups
,items
...) - 子组(字段:
group
,items
...) - 项目(字段:
enabled
,description
...)
这些实体具有关系:
- A
SubGroup
属于 aGroup
(aGroup
拥有多个SubGroup
) - An
Item
可以属于 aGroup
或 aSubGroup
(一次只能属于一个)
还有一些特殊的规则:
Item
属于 a的 anGroup
会继承给所有相关的SubGroup
Item
由 aSubGroup
从其继承的一个Group
可以被覆盖(我称它为继承是因为它的感觉,由父级继承的东西可以被覆盖或按原样使用)- 我拥有的主要覆盖用例是该
enabled
字段,因为在某些情况下我们可能希望禁用通过继承而来的项目
- 我拥有的主要覆盖用例是该
- 不要在数据库中复制内容(尤其是项目)(在应用程序级别查询数据库模型时应完成继承)
这个例子很简单,但实际情况要复杂一些,可以有更多的“SubGroup”级别,比如“SubSubGroup”,所以结构也应该优雅地处理这些
尝试 1
起初,我想象了一种传统的关系:
如果不是那些“特殊规则”,这会很好。因为这种结构无法覆盖继承的Item
.
因此,我也再次尝试处理这些问题。
尝试 2
ItemOverride
除了现有的实体Group
(SubGroup
和Item
该实体ItemOverride
包含以下字段:
- 项目 ID
- 实体类型(
Group
或SubGroup
) - EntityId(与选定的 id 相关的 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
模型将“无用地”复制其大部分字段,并且添加/更新/删除字段将不得不在两个表中而不是一个表中完成
所以,我不知道这个设计是否“足够好”,或者可以改进/简化。如果您知道的话,我有兴趣潜入具有此类继承/覆盖需求的类似项目。
概括:
我的第二次尝试似乎符合我的需求,如果我必须立即开始,我会使用它,因为我不知道如何改进它。
这种设计没有数据冗余,但仍然不清楚当 aSubGroup
继承 aGroup
时如何处理数据覆盖Item
。如果覆盖仅限于required
字段,那么它相当容易,但如果它有很多字段,那么维护起来就会变得有点复杂。使用模型/表继承也可能使事情复杂化,因为我们不想存储非覆盖值,因此希望允许表null
中的所有字段(如果我们在实体ItemOverride
中强制执行不可为空的规则,这可能是不可能的Item
因为它们也将应用于ItemOverride
)
问题:有没有办法同时使用继承和覆盖而不复制列配置和数据本身?
作为记录,我正在使用 Django。其强大的内部 ORM 可以优雅地处理ContentTypes
DynamicRelationship,它们允许使用模型的字段引用动态实体。(我称之为EntityType/EntityId
),这就是为什么第二次尝试设计是这样设计的原因之一(更容易依赖我的框架提供的东西)。但我对完全不同的可能性/选择持开放态度。
解决方案
推荐阅读
- python - 如何通过按下按钮(python)将我的变量提高 1?
- javascript - 如何访问嵌套的javascript数组中的特定字段
- r - 如何将 for 循环的每次迭代的结果恢复到自己的矩阵中?
- kotlin - build.gradle.kts 遵循 githubs 指南:配置 Gradle 以与 GitHub 包一起使用。但它未能找到“来自”功能
- python - 在一个数组中组合数组
- python - 如何让python文件复制自己然后执行另一个副本一次?
- pre-commit-hook - 在子文件夹中使用 setup.cfg 预先提交 flake8
- java - 无法从 MySql 获取特定数据
- python - 时间减法熊猫
- javascript - 在 iOS for iPad 上浏览器输入 type="date" 的 Onchange 行为