如何建模与不同类型对象的关系
How to model relation to different type of objects
我正在开发用于创建和存储打印布局的软件。
- 一个布局由一系列页面组成。
- 每个页有一个或多个栏
- 在每个列中会有一个或多个元素
- 列中的元素是有序的:有固定的元素顺序
- Elements可能是"text"或"image"类型(为了简单起见,实际上还有很多类型)
- 不同的元素有不同的属性。例如。图片有资源 url,文本有字体。请参阅发布末尾的示例代码。
我的问题是关于对列和元素之间的关系建模。
想法 #1:一个 table 用于所有元素
这真的很简单。将所有属性作为列添加到 table 并使用 N:N 关系来模拟列和元素之间的关系。
关系可能如下所示
column_idelement_id顺序
000000010000000010009
000000010000000020012
000000020000000060003
这对我来说似乎不太吸引人,因为存储元素的 table 会被空条目污染,例如对于图像元素,所有 font
列都是空的。如果我考虑我拥有的所有不同的元素类型(大约 10 种),情况会变得更糟。
好处:SQL查询比较简单:
select * from
relation_table R inner join elements E
on R.element_id = E.id
where R.column_id = FIXED_COLUMN_ID
想法 #2:每种类型的元素一个 table
元素建模非常简单,只需为 class 元素的所有属性创建一列并添加特定元素类型的属性,例如图像。
但是如何对关系建模 column:element?
我的第一种方法是尝试向关系中添加一列,指定元素类型,该元素将直接映射到相关 table:
column_idelement_id顺序element_type
000000010000000010012text
000000010000000020003图片
000000020000000060005图片
这当然有效,但检索特定列元素的所有 sql 查询都会变得相当复杂。
问题
是否有一种方法可以将想法 #1 的 sql 查询的简单性和想法 #2 的更准确的数据库建模结合起来?
你是如何解决这个问题的?
P.S.: 在其他情况下,我会切换到基于 nosql 的数据库,但这是不可能的:-(
<?php
// Sample code of element structure
class element {
protected $id;
protected $order;
// more properties, getters and setters...
}
class image extends element {
protected $image;
// more properties, getters and setters...
}
class text extends element {
protected $font;
// more properties, getters and setters...
}
?>
我认为您最好从一个 table 元素开始,然后添加连接 tables 以获得各种元素类型所需的额外信息。
在数据库设计中将数据建模为 real-world 实体通常是错误的,但退后一步并根据数据的内部依赖性进行建模要好得多。这些通常是一致的(并且这样做的频率足以使 real-world 实体焦点看起来很有吸引力)但是当你 运行 遇到它们不一致的情况时,你会感到悲伤。
在这里,您有关于查询和排序的问题,这些问题在单个 table 中解决起来微不足道,但如果有很多 table 问题,就会让您很头疼。
让我专注于混乱的部分:"Different elements have different properties. Eg. images have a resource url, text has a font." 正如您所说,这需要大量可为空的列或大量不同的表。无论哪种情况,都是一团糟。
一个解决方案...将那些 "different elements" 放入 JSON 的东西集合中。将它放在一个列中,让应用程序对其进行解码并利用这些东西。
使用该解决方案,结构仍在数据库中,但细节留给应用程序。似乎是一个公平的权衡。
查看 EAV 的其他讨论。
我正在开发用于创建和存储打印布局的软件。
- 一个布局由一系列页面组成。
- 每个页有一个或多个栏
- 在每个列中会有一个或多个元素
- 列中的元素是有序的:有固定的元素顺序
- Elements可能是"text"或"image"类型(为了简单起见,实际上还有很多类型)
- 不同的元素有不同的属性。例如。图片有资源 url,文本有字体。请参阅发布末尾的示例代码。
我的问题是关于对列和元素之间的关系建模。
想法 #1:一个 table 用于所有元素
这真的很简单。将所有属性作为列添加到 table 并使用 N:N 关系来模拟列和元素之间的关系。
关系可能如下所示
column_idelement_id顺序
000000010000000010009
000000010000000020012
000000020000000060003
这对我来说似乎不太吸引人,因为存储元素的 table 会被空条目污染,例如对于图像元素,所有 font
列都是空的。如果我考虑我拥有的所有不同的元素类型(大约 10 种),情况会变得更糟。
好处:SQL查询比较简单:
select * from
relation_table R inner join elements E
on R.element_id = E.id
where R.column_id = FIXED_COLUMN_ID
想法 #2:每种类型的元素一个 table
元素建模非常简单,只需为 class 元素的所有属性创建一列并添加特定元素类型的属性,例如图像。
但是如何对关系建模 column:element?
我的第一种方法是尝试向关系中添加一列,指定元素类型,该元素将直接映射到相关 table:
column_idelement_id顺序element_type
000000010000000010012text
000000010000000020003图片
000000020000000060005图片
这当然有效,但检索特定列元素的所有 sql 查询都会变得相当复杂。
问题
是否有一种方法可以将想法 #1 的 sql 查询的简单性和想法 #2 的更准确的数据库建模结合起来?
你是如何解决这个问题的?
P.S.: 在其他情况下,我会切换到基于 nosql 的数据库,但这是不可能的:-(
<?php
// Sample code of element structure
class element {
protected $id;
protected $order;
// more properties, getters and setters...
}
class image extends element {
protected $image;
// more properties, getters and setters...
}
class text extends element {
protected $font;
// more properties, getters and setters...
}
?>
我认为您最好从一个 table 元素开始,然后添加连接 tables 以获得各种元素类型所需的额外信息。
在数据库设计中将数据建模为 real-world 实体通常是错误的,但退后一步并根据数据的内部依赖性进行建模要好得多。这些通常是一致的(并且这样做的频率足以使 real-world 实体焦点看起来很有吸引力)但是当你 运行 遇到它们不一致的情况时,你会感到悲伤。
在这里,您有关于查询和排序的问题,这些问题在单个 table 中解决起来微不足道,但如果有很多 table 问题,就会让您很头疼。
让我专注于混乱的部分:"Different elements have different properties. Eg. images have a resource url, text has a font." 正如您所说,这需要大量可为空的列或大量不同的表。无论哪种情况,都是一团糟。
一个解决方案...将那些 "different elements" 放入 JSON 的东西集合中。将它放在一个列中,让应用程序对其进行解码并利用这些东西。
使用该解决方案,结构仍在数据库中,但细节留给应用程序。似乎是一个公平的权衡。
查看 EAV 的其他讨论。