数据库设计:Meetup.com中的用户配置文件

时间:2011-11-03 03:10:46

标签: mysql database database-design normalization

在Meetup.com中,当您加入聚会小组时,通常需要为该特定小组填写个人资料。例如,如果您加入电影聚会小组,则可能需要列出您喜欢的电影类型等。

我正在构建一个类似的应用程序,其中用户可以加入各个组并为每个组完成不同的个人资料详细信息。假设有两种可能性:

  1. 用户可以创建自己的组并定义要求用户加入该组的详细信息(因此,有点动态 - 可能暗示至少需要EAV设计)。
  2. 开发人员现在决定要创建哪些组,并指定要求加入该组的用户的详细信息(意味着将预定义配置文件详细信息并将其“硬编码”到系统中)
  3. 对此类数据进行建模的最佳方法是什么?

    更详细的例子:

    “电影观众”组要求其成员指定以下内容:

    • 名称
    • 出生日期(用于计算会员年龄)
    • 性别(必须从“男性”或“女性”中选择)
    • 收藏类型(必须从指定类型列表中选择1个或多个)

    “极限运动”组要求其成员指定以下内容:

    • 名称
    • 喜欢的活动描述(叙述形式)
    • 邮政编码

    最重要的是,每个小组可能需要加入其小组的成员提供不同的详细信息。理想情况下,我希望任何人创建一个组(ala MeetUp.com)。但是,我还需要能够很好地查询成员(例如找到所有年龄在25到30岁之间的女性电影观众)。

7 个答案:

答案 0 :(得分:7)

对于这样的事情....你想要最大规范化,所以你不会在任何地方重复数据。因为您的用户定义的表可能包含相同类型的记录,所以我认为您可能需要超过3NF

我的建议是这样 - 爆炸你的桌子,以便你有一些接近6NF的EAV,这样用户必须回答的每个问题都有自己的表格。然后,您的用户创建的表将引用您的一个问题表。这避免了重复数据问题。 (例如,您不希望“MovieGoers”组中的条目名为“John Brown”,而“极限运动”组中的条目名称为“Johnny B.”,对于同一用户;您也不要我希望他的“你最喜欢的颜色”的答案是一组中的“蓝色”和另一组中的“红色”。任何可以跨组的数据,如常见问题,都会以这种形式标准化。)

这样做的主要缺点是你最终会得到很多表,而你可能想为统计查询创建视图。但是,就纯数据完整性而言,这将很有效。

请注意,如果你真的想要,你可能只能将公共字段分解出去。常见字段的示例包括姓名,位置,性别等;你也可以对常见的问题做同样的事情,比如“你最喜欢的颜色是什么”或“你有宠物”或者那种程度的东西。不跨组的特定于组的问题可以存储在该组的单独表中,未爆炸。我不建议这样做,因为它不像纯6NF选项那样灵活,你冒着重复的风险(你如何预先确定哪些问题不是常见的问题?)但如果你真的想要,你可以这样做。

这里有一个关于6NF的好问题:Would like to Understand 6NF with an Example

我希望这有点意义,我希望它有所帮助。如果您有任何疑问,请发表评论。

答案 1 :(得分:6)

实际上,这正是SQL不是正确解决方案的问题。忘记规范化。这正是NoSQL文档存储的工作。每个用户都是一个文档,有一些必要的字段,如id,name,pwd等。每个组都增加了添加一些字段的可能性。唯一字段可以具有名称group-id-prefixed,共享字段(掌握一些更一般的概念)可以使该字段名称免费。

除了用户(和组)之外,您将拥有包含名称,类型,可能值......的字段描述,这对于文档存储也非常有用。

如果您从一开始就使用键值文档存储,那么您可以获得构建数据的自由形式 plus 查询它们(虽然不是通过SQL,但是通过这个或那个NoSQL数据库提供的方式) )。

答案 2 :(得分:1)

首先我要注意,以下结构只是数据库的基础,您需要扩展/缩小它。

DB中有以下实体:

  • 用户(仅限用户)
  • 组(任何组)
  • 模板(合并到模板中以简化分配的要求列表)
  • 要求(单项要求。例如:出生日期,性别,最喜欢的运动)

"建模":

**User**
user_id
user_name

**Group**
name
group_id

user_group
user_id (FK)
group_id (FK)

**requirement**:
requirement_id
requirement_name
requirement_type (FK) (means the type: combo, free string, date) - should refers to dictionary)

**template**
template_id
template_name

**template_requirement**
r_id (FK)
t_id (FK)

下一步是为存储限制建模适当的模式,即验证任何模板中任何需求的规则。我们必须将它分开,因为对于不同的组,相同的限制可能不同(例如:"年龄")。您可以使用下表:

**restrictions**
group_id
template_id
requirement_id (should be here as template_id because the same requirement can exists in different templates and any group can consists of many templates)
restriction_type (FK) (points to another dict: value, length, regexp, at_least_one_value_choosed and so on)

所以,正如我所说,这是基础。您可以随意简化此架构(清除表格,组的多个模板)。或者,您可以更方便地添加创建和发布temaplate,要求等的机会。

希望您觉得这个想法很有用

答案 3 :(得分:0)

您可以将此类数据保存为JSON或XML(结构,数据)

用户表

  • Userid
  • 用户名
  • 密码
  • 群组 - >所有组的JSON数组

GroupStructure表

  • GROUPID
  • 组名
  • 群组结构 - > JSON结构(带有指定的字段)

GroupData表

  • 用户ID
  • GROUPID
  • Groupdata - > JSON数据

答案 4 :(得分:0)

我认为这涵盖了大部分限制因素:

users
user_id, user_name, password, birth_date, gender

1, Robert Jones, *****, 2011-11-11, M

group
group_id, group_name

1, Movie Goers
2, Extreme Sports

group_membership
user_id, group_id
1, 1
1, 2

group_data
group_data_id, group_id, group_data_name

1, 1, Favorite Genres
2, 2, Favorite Activities

group_data_value
id, group_data_id, group_data_value
1,1,Comedy
2,1,Sci-Fi
3,1,Documentaries
4,2,Extreme Cage Fighting
5,2,Naked Extreme Bike Riding

user_group_data
user_id, group_id, group_data_id, group_data_value_id

1,1,1,1
1,1,1,2
1,2,2,4
1,2,2,5

答案 5 :(得分:0)

我遇到过类似的问题。我不确定这是否是针对您具体情况的最佳建议,但请考虑一下。

  1. 提供一种将数据存储为XML或JSON的方法,或者用于分隔数据的其他格式,但基本上将其存储在没有特定格式的字段中。

  2. 提供存储该数据定义的方法

  3. 为数据提供查找/索引表。

  4. 这是已经表明的技术组合。

    基本上,您可以为客户创建一些界面,以便为他们想要保存的内容创建“表单”。此表单将指示他们希望从用户获得哪些信息。它还会指出您要搜索的信息。

    将此信息保存到定义表中。

    然后使用定义表来描述用于输入数据的用户界面。

    输入用户数据后,将数据(如xml或其他数据)保存到具有唯一ID的一个表中。同时,另一个表将作为索引填充

    id保存xml数据的位置 字段数据的名称存储在 存储的现场数据的值。 数据定义的id。

    现在当搜索开始时,通过名称,值和定义id搜索索引表中的信息并获取存储在表中的xml / json(或其他)数据的id应该没有问题数据表格已存储。

    检索后,该数据应该可以转换。

    我对这里的细节非常粗略,我希望这足以让你开始。如果您需要任何解释或其他详细信息,请告诉我,我们将很乐意为您提供帮助。

答案 6 :(得分:0)

如果你没有坚持使用mysql,我建议你使用提供内置array数据类型的postgresql。

您可以在groups表中定义一个varchar字段数组来存储组特定字段。存储您可以在成员资格表中执行相同操作的值。

与基于字符串解析的xml类型相比,这种数组方法非常快。

如果你不喜欢数组方法,你可以检查xml数据类型和一个可选的hstore数据类型,这是一个键值存储。