2009-12-20 174 views
1

我想爲我寫的論壇腳本中的每個帖子添加一個like/dislike-upvote/downvote-type功能(很像這裏的SO)。我有兩個難題試圖弄清楚它是如何完成的:如何管理基於AJAX的「喜歡/不喜歡」功能?

1)我找不出一個可以高效完成的數據庫模式。我可以使用單獨的`likeordislike`表來創建用戶和帖子之間的關係(xyz喜歡帖子#123),或者我可以在`posts`表中使用\'text \'類型的列,列出所有用戶已經喜歡(或不喜歡)該帖子。後者當然意味着我必須解析用戶ID的字段才能使用它。

2)確保用戶不會喜歡/不喜歡一個帖子兩次。

這可能是微不足道的,但我只能想到在服務器端進程上進行大量mysql調用的方式。謝謝。

回答

2

(類似答案揚Hančič這裏,但我決定我採取的收視率是足夠不同的...)

你一個單獨的表來存儲喜歡/不喜歡的最初的想法是絕對的路上我會去。我會把索引放在兩個主要的列(玩家ID和帖子ID)上,這對下一個關鍵點至關重要。

例如:

create table users (
    userId varchar(254) not null, 
    -- ... 
    primary key (userId) 
) 
ENGINE=...; 

create table posts (
    postId int(11) not null, 
    title varchar(254) not null, 
    content text not null, 
    -- ... 
    primary key (postId) 
) 
ENGINE=...; 

create table userPostRatings (
    userId varchar(254) not null, 
    postId int(11) not null, 
    rating int(2) not null, 
    -- ... 
) 
ENGINE=...; 

create index userPostRatings_userId on userPostRatings(userId); 
create index userPostRatings_postId on userPostRatings(postId); 

我然後使用連接查詢(是否在存儲過程中,在代碼,或在視圖中)以獲得交的信息,例如:

select p.postId, p.title, p.content, avg(r.rating) 
from posts p 
left outer join userPostRatings r on p.postId = r.postId 
where p.postId = ? 
group by p.postId; 

(這將返回NULL對於普通的沒有任何等級任何發佈。)

雖然這是一個連接,因爲在的指標, 0表,這是一個相當有效的。

如果您發現一起被殺死你(非常高併發網站做),那麼你可能需要去正常化一月建議的方式有點,通過添加平均得分列posts並保持更新。您只需更改查詢即可使用它。但我不會開始非規範化,這是更多的代碼和可以說是不成熟的優化。你的數據庫用於跟蹤這些信息;只要您複製它正在跟蹤的信息,就會引入維護和同步問題。這些可能最終是合理的,但我不會開始認爲我的數據庫無法幫助我。如果在特定情況下加入是一個問題,則進行調整(如果您提前計劃)並不是什麼大問題。

+0

感謝您的詳細解答,它清除了很多東西。現在,我可以開始工作後,我的數據庫管理技能刷了一下:) – mathon12

+0

是否有可能修改查詢的方式,將返回所有職位,即使那些尚未評級? (沒有條目進入'userPostRatings'表。)在這種情況下,可能將'avg(r.rating)'設置爲null?謝謝。 – mathon12

+0

Doh!對不起,我不知道爲什麼我在那裏使用內連接。只需將'inner join'更改爲'left outer join'即可。 –

3

製作一張單獨的表格,您可以在其中跟蹤誰喜歡什麼,誰不喜歡。該表將被用於檢查用戶是否已經做了一些事情,所以你可以阻止他做兩次。 然後添加另一個字段(如果您將有票)或兩個(如果您將有喜歡/不喜歡),您將存儲喜歡/不喜歡或得分的總數,所以你不必計算這個每當你顯示帖子時當然,當有人對帖子進行投票時,您會更新本專欄(或專欄)。

而且不要打擾禁用投票鏈接。只要檢查用戶是否已經投票,當他點擊鏈接並拒絕他投票,如果他已經投了一個。