2010-08-10 21 views
0

這是一個有點不同於典型的「我如何製作標記系統」的問題,這個問題已經在SO和其他地方。如何實現多用戶標記*投票*系統(即像Slashdot的故事標籤)

我想標記衆包,因此您不必依賴每個文檔的所有者來完整列出適用的標籤。與此同時,我不想讓一個隨意的學生通過故意混淆大量文檔來弄亂每個人的標籤。

這樣的系統是如何工作的?例如,Slashdot.org依賴類似的東西來提供故事標籤。 (永遠不必修改代碼,我有興趣聽到更多有關如何工作的。)

我們使這更具體:假設我的標籤DB模式是這樣的:

doc:  id, name, ... 
tag:  id, tag_name 
doc_tag: doc_id, tag_id, user_id 

現在,每個用戶可以將他/她自己的標籤分配給文檔。確定共識的一種方法是查看使用特定標籤標記文檔的人員比例。這導致下面的SQL語句的怪異。

SELECT 
    doc_id, tag_id, 
    num_times_tagged, taggers_count, 
    num_times_tagged/taggers_count AS popularity 

FROM doc_tag 

LEFT JOIN (
    SELECT doc_id, tag_id, COUNT(*) AS num_times_tagged 
    FROM doc_tag GROUP BY doc_id, tag_id 
) num_times 
ON doc_tag.doc_id = num_times.doc_id AND 
    doc_tag.tag_id = num_times.tag_id 

LEFT JOIN (
    SELECT doc_id, COUNT(DISTINCT user_id) AS taggers_count 
    FROM doc_tag GROUP BY doc_id 
) num_taggers 
ON doc_tag.doc_id = num_taggers.doc_id 

GROUP BY doc_tag.doc_id, doc_tag.tag_id 

我該說這個完全錯了嗎?這似乎是一個非常昂貴的查詢。假設我只想獲取每個文檔和頂部標籤的列表 - 我怎麼會爲此寫入連接?我不想爲獲取的每個文檔運行此查詢!

感謝您的任何建議。

大衛

+0

如果你想減少加載查詢時間(選擇),你可以使用觸發器更新助手錶,因爲人們正在重新標記。這個輔助表可以是精益的,適當的索引等,並加載速度快。這會將負載轉移到不同的時刻,並且可能會給您一個不太乾淨的/ KISS數據模型,但是會是一種選擇。 – Tobiasopdenbrouw 2010-08-10 08:14:49

+0

嗯 - 我之前沒有使用觸發器。你能舉一個這樣的例子嗎?那麼輔助表模式會是什麼 - 標記ID,文檔ID,#計數? – PBJ 2010-08-10 08:29:29

+0

鏈接後面是觸發器的介紹。 http://www.sqlteam.com/article/an-introduction-to-triggers-part-i。至於助手錶模式:這取決於你真正想要展示的內容,但你的例子可能是一個開始(也許你需要的全部)。 – Tobiasopdenbrouw 2010-08-10 10:07:14

回答

0

這裏有一個更清潔的查詢:

SELECT 
    doc_id, 
    tag_id, 
    COUNT(*) AS num_times_tagged, 
    COUNT(DISTINCT user_id) AS taggers_count, 
    COUNT(*)/COUNT(DISTINCT user_id) AS popularity 

FROM doc_tag 
GROUP BY doc_tag.doc_id, doc_tag.tag_id 

而且,我不熟悉所有RBDMS,但如果你使用SQL Server,你可以創建一個視圖,然後聚集在視圖頂部的索引。這會減慢你的插入到doctag,但讓你從那個視圖讀取真的很快。