讨论论坛中upvote / downvote的数据库设计?

时间:2017-07-08 15:16:24

标签: mysql django database database-design

我有一个网站,里面有一个讨论论坛。所有问题都有唯一ID,答案也有唯一ID,外键引用问题ID。

我有一个用户登录。使用ajax,我可以发送数据(upvote / downvote,QID / AID,用户名)。但是几乎没有问题。

  1. 每当用户重新登录时,我希望当他打开一个问题时,应该显示他之前的upvotes和downvotes。

  2. 用户无法多次upvote / downvote同一个问题。就像他向+1提出一个问题一样,他只能将其投票,而不是再次投票。

  3. 根据我的解决方案。我正在考虑维护一个表,其中username是主键,另一个属性是他所做的所有upvotes和downvotes的列表。例如:

    (username, array)
    (baqir, up_A001 up_A050 down_Q011 up_Q123)
    

    每当用户登录时,我都会使用此数组并确保用户之前的所有upvotes和downvotes都是原样。如果有新的投票,我将其添加到数组中。

    有没有更好的解决方案?

    P.S。不是必要的,而是我当前的数据库结构。

    class Question(models.Model):
        QID = models.CharField( default="",max_length=1000, primary_key=True)
        title = models.CharField(max_length=30, default="")
        description = models.CharField(max_length=1055, default="")
        date = models.DateTimeField(default=datetime.now, blank=True)
        username = models.CharField(max_length=6, default="")
        votes = models.IntegerField(default=0)
        approved = models.BooleanField(default=False)
    
        def __str__(self):
            return self.title
    
    class Answer(models.Model):
        AID = models.CharField(max_length=1000, default="", primary_key=True)
        QID = models.ForeignKey(Question,on_delete=None)
        description = models.CharField(max_length=1055, default="")
        date = models.DateTimeField(default=datetime.now, blank=True)
        username = models.CharField(max_length=6, default="")
        votes = models.IntegerField(default=0)
        approved = models.BooleanField(default=False)
    
        def __str__(self):
            return self.AID
    

    我正在使用Django。而且我基本上想要任何stackoverflow实现他们的问题和答案投票。

4 个答案:

答案 0 :(得分:3)

什么阵列人,你在说什么?您为每个Q / A或每个用户创建另一个表,或者您只链接两个内容的表,即用户和Q / A及其可以重复键的投票(此表没有主键)。 任何阵列式的东西都是时间和精力的损失,无论如何都违背了良好的数据库设计规则。

表保持投票的例子:

Table votes:
    UID | QID | AID | VOTE

因此,您可以将每个用户与他/她投票的每个问题或答案联系起来。 QID或AID可以为NULL。当你提出一些问题时,你只需检查表格投票是否有任何关于它的说法以及与之相关的答案。如果当前的QID和UID匹配并且您得到结果,那么您只需采取相应的行动。

如果你有很多用户,这有可能会很慢,但基本上会很好用。

第二个解决方案是将你的问题/答案与另一个表格联系起来,只保留在做某事的用户(上/下投票)。这将使DB看起来更加混乱但是当您的用户找到给定的Q及其答案时,您只需检查此表是否有关于访问者的信息。如果我不够清楚,我重复一遍,每个Q和/或A的新表。

您可以反向应用相同的技术,即将用户连接到包含用户投票的所有Q / A的表,这可能是保持秩序和效率的最佳方式。因此,每次用户访问任何Q页面时,您都会检查他/她是否有该Q的历史记录。

没有数组,没有废话。只需一个额外的请求来检查当前查看的Q / A的状态。

答案 1 :(得分:1)

Upvote和Downvote场景可以使用代码处理,如果最后一次投票是upvote用户只有权限downvote,如果用户downvote他有权进行upvote,但为了保持状态,你告诉你可以保留历史记录一个数组。

答案 2 :(得分:1)

Dalen建议的第一种方法似乎最好

制作一个单独的表来存储投票,并在执行任何上/下操作之前,检查用户之前是否做过任何类似的操作。

如果他之前已完成相反的操作,请删除/停用其在表格中的上一个条目并创建一个新条目。 如果他之前已经针对该问题执行了相同的操作,则不执行任何操作,因为他的上/下投票已被计算在内。

强烈建议为这些任务制作表格,因为它不仅可以使您的工作更轻松,而且还可以为您提供更多的灵活性,例如您可以为每个操作添加时间戳来跟踪历史记录,或者您可以计算查询表格以查找对问题执行的总操作

答案 3 :(得分:0)

CREATE TABLE QuestionVotes (
    UID ...,  -- User id
    QID ...,  -- Question id
    vote ENUM('up', 'down'),
    PRIMARY KEY(QID, UID)  -- for finding voting status of a question
    INDEX(UID, QID)  -- if you need the votes by a user
) ENGINE=InnoDB;   -- to get benefit of clustered PK

同样为AnswerVotes

Upvote / downvote:查看该行是否存在,如果不存在,则创建该行。如果存在行,则删除该行或者抱怨用户上升/下降两次。

不要使用数组。它会变得太痛苦。

如果Django不能让你拥有复合PRIMARY KEY,那就放弃Django。

表中没有1000个字符键。磁盘空间和性能将受到影响。

用户只能是6个字符。缩放规模并不乐观?