问题描述
我正在使用带有graphql的Postgresql处理网站上帖子的一些数据。这些帖子有些复杂,我只是不确定组织数据的最佳方法是什么。这样做的原因是,帖子可以属于不同的类型,因此不同类型的数据结构可能会有所不同。例如,我有一个文本类型和一个视频类型,其中视频类型需要一个url,缩略图和一个描述,而文本仅需要一个描述。我不确定组织数据的最佳方法是什么。
是否可以像下面这样链接多个表?因此,换句话说,有可能根据posts表中的ItemID查询并获取正确的数据,然后将其从相应的表中拉出。
帖子列表如下:
|-----------|----------|----------|----------|
| ID | Type | Title | ItemID |
|-----------|----------|----------|----------|
| 1 | Text | My text | 1234 |
|-----------|----------|----------|----------|
| 2 | Video | A vid | 3456 |
|-----------|----------|----------|----------|
视频表如下
|-----------|----------|----------|----------|
| ID | Desc | URL. | Thumbnail|
|-----------|----------|----------|----------|
| 3456 | .... | .... | .... |
|-----------|----------|----------|----------|
文本表看起来像
|-----------|----------|
| ID | Desc |
|-----------|----------|
| 1234 | .... |
我能想到的另一种方法是只为帖子提供一个表,并且只包含不需要的数据,并具有所有字段的可能性。然后,我将根据需要将其组织在前端。
对于如何最好地解决此问题的任何想法或建议,将不胜感激!
解决方法
我看不到您的数据模型有什么问题,除了我将使用两个不同的列而不是itemid
。它们每个都有一个外键,一个到视频表,一个到文本表。检查约束条件确保只有IS NOT NULL
个和type
匹配,类似
CHECK (type = 'text' AND text_id IS NOT NULL AND video_id IS NULL OR
type = 'video' AND text_id IS NULL AND video_id IS NOT NULL)
这样,您可以在表之间使用外键,这对于数据完整性至关重要。
,我不确定您的设计,但是我不知道总体规格。 您将不得不在数据库设计中使用一些代码。首先,是一个网页表,我还假设您的网站上有多个页面。
WEBPAGE表:WebPageID(PK),WebPageDesc
然后,我们为每个网页添加一个表格以供发布。 这样会为每个帖子分配一个ID。
POST表:PostID(PK),WebPageID(FK)
如果只有一页,那么您不需要WEBPAGE表,可以将POST表更改为;只是POST表:PostID(PK)
然后,正如您所得出的,一个表用于存储所有视频帖子,另一个用于存储文本。
VIDEOPOSTS表:VideoPostID(PK),VideoDesc,VideoURL
TEXTPOSTS表:TextPostID(PK),TextDesc
现在,您只需要几个表格即可将不同类型的帖子链接回网页。两者都使用复合主键,省去了ID列。
POSTSVIDEOPOSTS表:PostID(PK)(从FK到发布表),VideoPostID(PK)(从FK到videoposts表)
POSTSTEXTPOSTS表:PostID(PK)(从FK到发布表),TextPostID(FK)(从FK到textposts表)
进一步思考:
您可以在每个帖子旁边添加一个已删除标志,以决定是否应将其包含在网页输出中,具体取决于用户是否可以删除帖子。
采用上述设计,将很难按正确的顺序对帖子进行排序,因为您是从两个单独的表中检索帖子的。我认为这种设计是标准化的。
我只是不确定它是否100%正确。我需要查看更多规格才能更好地进行设计。也许,如果有发布日期的日期时间,那将使排序更加容易?
但是我不能100%确信使用帖子表中的“类型”列的原始帖子中的原始设计是正确的...
设计是否需要归一化?
很高兴上述内容被其他人批评,我敢肯定它需要进一步的工作!
,您尝试的检查在正确的轨道上,但不太正确。首先,结构“类型IS'视频'”无效。 Null值使用IS检查,而其他值使用comparison operators检查。其次,正如Laurenze所指出的,您必须确保一个且只有一个外键标识符为空。在这些条件下,我们得到:
check ( ( (vedioidentifier is null and textidentifier is not null)
or (vedioidentifier is not null and textidentifier is null)
)
and ( (type = 'video' and vedioidentifier is not null)
or (type = 'text' and textidentifier is not null)
)
)
对CamelCase的警告: Postgres维护CamelCase名称以仅当标识也用双引号(“)括起来时标识。如果这样做,大多数情况下,始终对每个引用都使用双引号。引用Postgres将所有标识符折叠成小写。更好的方法是使用snake_case标识符名称。