2017-07-08 42 views
1

我有一個網站,有一個論壇。所有的問題都有唯一的ID,並且答案也有唯一的ID,外鍵引用問題ID。數據庫設計upvote/downvote在討論區?

我有一個用戶登錄。使用ajax,我可以發送數據(upvote/downvote,QID/AID,用戶名)。但幾乎沒有問題。

  1. 每當用戶在登錄後,我想,當他打開了一個問題,他以前upvotes和downvotes應顯示。

  2. 用戶無法多次提問/倒推同一問題。就好像他向+1提出了一個問題,他只能倒下它,而不是再次讚揚它。

根據我的解決方案。我正在考慮維護一張表,其中username是主鍵,另一個屬性是他所做的所有upvotes和downvotes的列表。例如:

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

每當用戶登錄時,我借這個陣列,並確保所有以前的upvotes和用戶的downvotes是因爲它是。如果有新的投票,我將它添加到數組中。

有沒有更好的解決方案?

P.S.不是necceassary,但我目前的數據庫結構。

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已經實現了他們對問題和答案的投票。

+0

不能讓你只提出問題/答案ID和用戶ID一個唯一的約束? – chris85

+2

有越來越多的人用PHP標記python問題。我不明白爲什麼。 – apokryfos

+0

你的意思是創建另一個表,(QID/AID,用戶名)作爲它的屬性? –

回答

1

什麼排列的人,你在說什麼?您可以爲每個Q/A或每個用戶創建另一個表格,或者只是鏈接兩件事情的表格,即用戶和Q/A及其可以重複鍵的表決(該表格沒有主鍵)。 任何類似陣列的事情都會浪費時間和精力,無論如何它都會違反良好的數據庫設計規則。

表保持投票舉例:

Table votes: 
    UID | QID | AID | VOTE 

所以你每個用戶他/她投每個問題或答案連接。 QID或AID可以是NULL。當你回答某個問題時,你只需檢查表格投票是否有任何關於它的說法和答案。如果當前的QID和UID匹配並且您獲得結果,則您只需採取相應措施。

如果你有很多用戶,這可能會變慢,但基本上會工作的很好。

第二種解決方案是將你的問題/答案與另一張表保存在只有做了某事的用戶(上/下投票)中。這將使數據庫看起來更加混亂,但是當你的用戶給予Q及其答案時,你只需檢查該表是否有關於訪問者的說法。如果我不夠清楚,我再重複一遍,每個Q和/或A都有新的表格。

您可以在相反的方向應用相同的技術,即將用戶連接到一個包含用戶投票的所有Q/A的表格,這可能是保持秩序和效率的最佳方式。因此,每次用戶進入任何Q頁時,都會檢查他/她是否有任何Q.歷史記錄。

沒有數組,沒有廢話。只需一個額外的請求來檢查當前查看的Q/A的狀態。

1

Upvote和Downvote方案可以使用代碼處理,如果最後一票是upvote用戶只有downvote的權限,如果用戶downvote他有權upvote,但爲了保持狀態,如你所說可以保留歷史記錄在一個數組中。

0

Dalen提出的第一種方法似乎最好

做一個單獨的表,用於存儲票,並執行任何向上/ downvote行動之前,檢查用戶是否做過任何類似的行動。

如果他已經完成相反的操作,則刪除/停用他先前在表格中的條目並創建一個新條目。 並且如果他已經執行了相同的之前的行動問題,則什麼都不做,因爲他的up/downvote已經被計入。

爲此類任務製作表格非常受歡迎,因爲它不僅可以讓您的任務更輕鬆,還會給您更大的靈活性,就像您可以爲每個動作添加時間戳以跟蹤歷史記錄,或者您可以點擊計算表上的查詢以查找對問題執行的總操作

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不讓你有複合主鍵,就放棄Django。

表中沒有1000個字符的鍵。磁盤空間和性能將受到影響。

用戶只能有6個字符。縮放比例不樂觀?