jrh*_*424 1 django polymorphism orm normalization relational-database
尽管我使用 Django 的 ORM 来实现这些表,但我有意将此作为一个一般性问题来构建。如果你想看一看,这是我的 Django 模型。
我有几个表具有以下关系:
Survey <--m2o-- Page <--m2o-- Category <--m2o-- Question <--m2o-- Choice <--?-- Response
| | | | |
|- name |-number |- name |- sortid |- sortid
|- sortid |- text |- text
|- text |- short
|- qtype
Run Code Online (Sandbox Code Playgroud)
m2o多对一的简写在哪里,每个表都有一个隐式主键,我的问题是关于如何组织响应表。
响应表应该与用户表有某种关系(取决于表定义,这可能是一对一或多对一)。该表的目的是存储用户对特定问题的回答。我遇到的问题是,根据问题类型,我需要将响应存储在响应表中的不同列类型中。例如一个表可能类似于:
| user | (question) | (qtype) | choice | response |
|------+------------+-----------------+-----------+-------------------------------|
| 1 | Q1 | Select One | A | False |
| 1 | '' | '' | B | False |
| 1 | '' | '' | C | True |
| 1 | .. | '' | D | False |
| 1 | Q2 | Select Multiple | 1 | True |
| '' | '' | '' | 2 | True |
| '' | '' | '' | 3 | False |
| '' | '' | '' | 4 | True |
| '' | Q3 | Long Text | NULL | "It was the best of times..." |
| '' | Q4 | Select Explain | A | False |
| '' | '' | '' | B | False |
| '' | '' | '' | C | False |
| '' | '' | '' | D (other) | True |
| '' | '' | '' | Explain | "I actually prefer bananas." |
Run Code Online (Sandbox Code Playgroud)
为了清楚起见,我添加了由关系隐式定义的列,因此不会出现在实际表中。它们用 表示( )。此外,choice实际上是一个外键。
似乎响应列可能需要是文本列。把它分成两列或更多列response-text,response-boolean感觉很乱。我们可以轻松地为单个用户拥有数百行。
我还考虑过像这样组织表格:
| user | survey | response (key-value store) |
|------+--------+--------------------------------------------|
| 1 | 1 | {"q1": "C", "q2": "1,2,4" |
| | | "q3": "It was the best of times..." |
| | | "q4": "Other: I actually prefer bananas."} |
| 2 | 1 | {...} |
| 3 | 1 | {...} |
Run Code Online (Sandbox Code Playgroud)
如果您解释您的定义在哪些上下文中不起作用,则加分。
如果你想想象我的情况,这里有一些关于我的上下文的注释:
我怀疑我的情况接近Wikipedia 上的N1NF示例。
我刚刚听说过多表继承或多态性,我不确定如何将它应用于这个问题。具体来说,我不确定哪些表会从继承中受益。例如,响应应该扩展选择吗?Page 应该扩展调查吗?
我是http://360test.nl/的首席架构师和开发人员,它使用调查来衡量团队绩效等。
我们的基本表结构与您的没有什么不同。
回答存储在一个相当简单的表中:
ID | Participation | Question | RawValue
Run Code Online (Sandbox Code Playgroud)
Participation是一位用户参与一项调查的 ID。Question是调查中一个问题的 ID。RawValue 存储一个单一的答案。它的格式取决于问题类型。它可以是单个数字(对于一个简单的“选择一个”问题)到更复杂的 json 结构(例如对于“在那些 Y 选择上分配 X 点”类型的问题)。问题类型知道如何序列化/反序列化数据有用的东西。
我们不在我们的表中使用继承。如果我们需要调查答案的在线查询(“有多少用户在调查 xyz 中选择了答案 3”),这是有道理的,但我们不需要那样。因此,我们可以使用我们简单的“通用” RawValue 列。当我们显示调查结果时,所有答案都会被加载,它们的值会根据问题类型进行反序列化和评估。如果我们需要更多特殊报告,我们会离线生成它们并将结果存储在某个地方。
我认为即使是您建议的方法(将一个参与的所有答案存储在一列中)也适用于我们,因为无论如何我们在执行评估时都会加载整个数据。
我并不是说我们的方法是最好的,但它对我们有用。
作为一般说明 - 规范化是一个重要的话题。但这并不意味着,一切都需要规范化。虽然我将核心域模型的持久表示归一化,但有时我会将严重非规范化的数据存储在数据库中,以供从域模型生成的报告中使用。重要的是您要知道它是非规范化的以及数据来自何处。
我使用我认为的CQRS架构编写了软件,我学到的一件事是非规范化可能是一件非常好的事情。一些 CQRS 专家建议每个网页一个表格,其中包含该页面所需的所有(非规范化)数据。虽然这不一定是您应该一直做的事情,但它表明并非在所有情况下都需要教科书规范化。
| 归档时间: |
|
| 查看次数: |
654 次 |
| 最近记录: |