【问题标题】:Database design for upvote/downvote in discussion forum?论坛中赞成/反对票的数据库设计?
【发布时间】:2017-12-12 17:57:59
【问题描述】:

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

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

  1. 每当用户重新登录时,我希望当他打开一个问题时,应该显示他以前的赞成票和反对票。

  2. 用户不能多次赞成/反对同一个问题。就像他将一个问题投票给 +1 一样,他只能投反对票,而不能再次投赞成票。

根据我的解决方案。我正在考虑维护一个表,其中用户名是主键,另一个属性是他所做的所有赞成和反对的列表。示例:

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

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

有没有更好的解决方案?

附:不是必需的,而是我当前的数据库结构。

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 为他们的问题和答案投票实现的东西。

【问题讨论】:

  • 您不能只将 questionid/answer id 和 userid 设为唯一约束吗?
  • 越来越多的人用 PHP 标记 Python 问题。我不明白为什么。
  • 您的意思是创建另一个表,其属性为 (QID/AID, username)?
  • 既不是python也不是php,只是一个数据库结构问题。我可以在 python 或 php 中做同样的事情。还是谢谢
  • 您已经在存储信息,所以添加一个唯一约束,表格将不允许插入额外的投票。

标签: mysql django database database-design


【解决方案1】:

什么阵型的人,你在说什么?您为每个 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 的状态。

【讨论】:

    【解决方案2】:
    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 不允许您拥有复合主键,请放弃 Django。

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

    用户只能是 6 个字符。不看好扩大规模?

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

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

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

        如果他之前做过相反动作,删除/停用他之前在表格中的条目并创建一个新条目。 如果他之前已经对问题执行了相同的操作,则什么也不做,因为他的赞成/反对票已经计入。

        强烈建议为此类任务制作表格,因为它不仅可以让您的任务更轻松,还可以为您提供更大的灵活性,例如您可以为每个操作添加时间戳以跟踪历史记录,或者您可以点击计数查询表以查找对问题执行的总操作

        【讨论】:

          猜你喜欢
          • 2012-03-09
          • 2012-12-15
          • 2012-06-06
          • 1970-01-01
          • 2013-11-16
          • 2015-10-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多