【问题标题】:User database design for marketplace-style app市场风格应用程序的用户数据库设计
【发布时间】:2014-05-29 22:33:19
【问题描述】:

由于我是数据库架构的新手,因此需要一些最佳实践智慧。这是针对市场类型的应用程序。我想建议的主要问题是处理用户。

我想要实现的是买家和卖家账户共享登录/注册功能和一些特性,但卖家账户具有销售、接收付款等能力。买家可以发送请求,卖家可以完成它们。基本上,卖家可以做买家可以做的所有事情,但还可以查看和完成请求,然后进行销售。

我会选择简单的角色,除了在产品和付款信息方面卖家的关系比买家更复杂。卖家还需要能够公开上市,并拥有公开的个人资料。我不确定拥有 1 个包含两种用户类型的大表是否适合此操作。

我目前的想法是在基本用户表和卖方表(也可能是买方特定表)之间使用多态关联:

用户(买家)

  • 姓名
  • 电子邮件
  • 加密密码
  • (其他身份验证字段)
  • 位置
  • 职业
  • meta_id
  • 元类型

卖家

  • 姓名
  • 位置
  • 职业

请求(属于买方和卖方)

  • 类型
  • 说明
  • 完成
  • buyer_id
  • seller_id

产品(属于卖家)

  • 说明
  • category_id
  • seller_id

如您所见,一个大问题是买家和卖家拥有重复数据这一事实。这样做的原因是因为当我显示卖家时,我不想执行多表查询,但也许这不是问题?另一种选择是先拥有用户基表,然后是买家和卖家表,但它们仍会包含重复信息。

接受所有可能性.. 最好的方法是什么?

【问题讨论】:

    标签: sql ruby-on-rails database database-design


    【解决方案1】:

    您可以使用数据库超类型和子类型来表示这种关系。

    对于您的示例,我会将数据模型分为两组:usersroles。一个角色可以是买家也可以是卖家,一个用户可以拥有零个或多个角色。

    然后我将创建以下逻辑实体来表示 角色 关系:

    超类型

    • UserRole(此名称可能过于笼统;我建议使用更能反映您的应用程序中买卖双方角色的名称)。

    子类型

    • 买家
    • 卖家

    对于您的物理设计,我会建议以下设计之一:

    1. 包含超类型实体的列以及每个子类型实体的列的单个表。检查约束可用于对子类型列强制执行非空约束。
    2. 一个表用于超类型,每个子类型实体都有一个单独的表。每个子类型共有的列存储在超类型表中,而其他列存储在相应的子类型表中。一个类型列被添加到超类型表中以指示实体的类型。每个子类型表都包含与超类型表的外键关系。
    3. 混合方法,结合了上述每个设计的各个方面。

    访问模式

    在决定如何对子类型和超类型关系建模时要考虑的一个因素是您的查询是否需要同时访问超类型和子类型表中的列。如果您的大多数查询将访问超类型和子类型表中的列,那么单个表可能是更好的设计。

    编辑 - 我建议使用第一个设计,除非有令人信服的理由为子类型创建单独的表。包含类型列的外键可用于将关系限制为特定子类型。

    将用户映射到角色

    要将用户分配给角色,您可以简单地在 User 表和超类型 (UserRole) 表之间创建多对多关系。

    【讨论】:

    • 感谢您的回答。我喜欢设计#2,这就是我一直想做的,但我最大的障碍是访问模式。买卖双方都有一个“名字”。如果我在访问买家或卖家时将其存储在 UserRole 中,我必须让 UserRole 知道名称。最大的问题是在列出卖家及其个人资料页面时。查询多个表似乎会影响性能并且是糟糕的设计,但如果替代方案是复制数据,那么我不确定。想法?
    • 我建议使用第一个设计。与第二种设计相比,您的查询将更易于编写并且执行得更好,因为您不需要将子类型表连接到超类型表。如果您决定使用第二种设计,您可以在超类型表和子类型表之间创建一个索引视图,以提高需要访问所有列的查询的性能。在第一个设计中,我不会担心子类型列的 NULL 值;可以使用 CHECK 约束来应用非空约束。
    • ...但是如果替代方案是复制数据,那么我不确定....除了超类型实体的主键值之外,您不需要将重复数据存储在任何子类型表。公共列只能存储在超类型表中。如果您决定为子类型创建单独的表,那么这些表只需要包含特定于子类型的列。
    【解决方案2】:

    您听说过多态性吗?

    您可以创建一个“母”类User(例如devise)并创建两个“子”类BuyerSeller

    好教程here

    【讨论】:

    • 是的,这正是我的想法:我目前的想法是在基本用户表和卖家表(也可能是买家特定表)之间使用多态关联。
    • 哦,好吧!我刚刚在pinkpanda/skeria 的一个项目中使用了它。检查AdminsCollaboratorsClientsUser (from Devise)
    【解决方案3】:

    假设所有用户都是买方|卖方,但不是两者,我会执行以下操作,我认为这基本上就是您的建议:

    人 // 我实际上会有一个 ROLE 表,并且只在 PERSON 表中包含 role_id 但这可能不会增加任何东西,除了复杂性之外,这取决于是否有关于您想要存储在数据库中的不同角色的数据

    卖家 person_id

    买家 person_id // 也许对于 BUYERS 没有任何额外的数据,但是如果你要实现数据库级别的外键约束,那么填充这个表将允许你约束一个实际的 BUYER

    然后是附加表。如果您使用外键约束来确保数据完整性,那么您将在特定表(BUYER、SELLER)上约束buyer_id 和seller_id,这不仅可以保证您对PERSON 的约束。

    如果人们既可以是买方又可以是卖方,那么我可能仍会使用此模型并扮演 BUYER_AND_SELLER 角色,但最好将列 is_buyer 和 is_seller 添加到 PERSON 以防您确信这些是唯一的您将永远支持的角色。

    【讨论】:

    • 理想情况下,用户可以同时是买家和卖家,更常见的情况是只是买家。使用这个模型,我可以将共享数据(例如姓名)放在我喜欢的 Person 表中,但是当我列出卖家时,我必须同时查询卖家表和 person 表以获取所有必要的卖家信息。想法?
    • 好吧,当您想要特定用户的所有数据时,您将在查询中加入表,因此您将执行一个查询,从多个表中提取数据(您可以加入 PERSON/BUYER和 PERSON/SELLER 或 PERSON/BUYER/SELLER,如果这更适合您的需求)。只要您正确索引 person_id 和外键引用,性能影响应该可以忽略不计。创建对数据用户隐藏联接并在一个视图中逻辑显示所有买方数据并在另一个视图中显示所有卖方数据的视图可能是有意义的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-23
    相关资源
    最近更新 更多