2012-07-12 39 views
0

我正在構建一個多站點平臺,類似於StackExchange,它有多個社區使用相同的平臺和共享數據。標籤架構

用戶可以像標記堆棧交換問題一樣標記其內容。創建標籤概念的最佳體系結構是什麼?

我想過的一些小筆記是別名(同義詞)的概念。另外我還想過,我希望標籤可以跨站點共享(所以可以從另一個站點查看同一主題的內容),但另一方面,不同社區的上下文可能會有所不同。例如,計算機中的「圖形」是一個數據結構,而數學則是其他的東西(只是我頭頂的一個隨機例子 - 不知道它是否重要)。

另外,如果我有英語和一個社區一個在法國...

你覺得呢?

+0

標籤如何管理?在大多數站點(如StackOverflow)中,用戶可以快速方便地創建標籤。標籤是否與正式類別相同,即嚴格在編輯過程中進行管理,還是他們是特設的,人羣智慧型的東西? – 2012-07-12 17:11:06

+0

與Stack類似,他們只是鍵入單詞。雖然我們可能需要一個最低水平來創建新的 – 2012-07-13 08:55:43

回答

0

我建議這樣的模式:

ERD

你保持可用標籤的列表,這些被應用到任何物品您使用的是標準的多對許多交集表標記。

要管理標記的同義詞,請在可用標記表上使用漸近關係。這假設各種標籤是同義詞,其中一個被認爲是「主要」標籤。

可用標籤有一個語言標誌來表示英語或法語。如果您爲加拿大政府或其他事情做這件事,並且需要確保所有內容都以兩種語言出現,您可以在AVAILABLE_TAG上添加一個漸進的一對一(未顯示),以鏈接相應的英文和法文標籤。

要跨站點共享標籤,請使用與SITE表的另一個多對多交叉點來顯示哪些標籤屬於哪個站點。如果這些標籤在每個網站上意味着不同的東西,我會避免在網站上共享標籤。

1

做到在一個完全規範化的方式,你需要這樣的事:

enter image description here

的MEANING_ITEM有以下指標:

  • {SITE_ID,MEANING_NO,ITEM_NO} - 爲主鍵自動創建並支持使用給定標籤高效搜索項目。
  • {ITEM_NO,SITE_ID,MEANING_NO} - 可以高效地查詢相反的內容:「獲取給定項目的標籤」。

注意:如果您的DBMS支持它,請考慮clustering此表。集羣表中的二級索引可能很昂貴(因爲它們需要包含整個PK的副本並可能導致雙重查找),但在這種情況下,兩個索引都包含相同的字段(因此所有「額外」字段都已存在於次級索引),並且沒有索引之外的字段,因此不需要進行雙向查找。通過聚類,你只需要消除(無用的)表堆,而只剩下兩個B樹。

這種模式具有以下特性:

  • 兩個標籤和物品的部位特異性地識別和您查詢默認站點特定的標籤。如果您想查詢標籤名稱而不考慮網站,只需在下面的查詢中從WHERE子句中省略SITE_ID = ...即可。由於TAG_NAME處於TAG PK的領先優勢,因此無需額外索引即可有效地滿足無站點查詢。
  • 項目不能標記來自「錯誤」網站的標籤。我們使用標識關係,這些關係沿着「菱形」依賴關係的兩個邊緣向下傳播SITE_ID,併合併到「菱形」(在MEANING_ITEM中)的底部,這就是我們保證的原因。
  • 標記同義詞有效地表示(在同一站點內具有相同含義的標記被視爲同義詞)。如果我們試圖在標籤上實現M:N自我關係,那麼就沒有可能發生的各種異常情況。
  • 由於標籤的含義是特定於站點的,所以同義詞也是站點特定的。
  • 意義表是存儲有關標記(如描述)的附加信息的自然地方,它將由所有同義詞共享。

我們將如何處理同義詞傳遞性?如果A,B和C是同義詞,我們只是存儲A-B和B-C,或者我們也存儲A-C?我們如何執行它?如果我們不強制執行它,我們需要某種遞歸查詢來選擇所有依賴關係。我們需要爲每個連接添加一行,浪費空間和性能。

要獲得項目特定標記的任何,你需要執行一個類似的查詢......

SELECT * 
FROM ITEM 
WHERE EXISTS (
    SELECT * 
    FROM TAG JOIN MEANING_ITEM ON 
     TAG.SITE_ID = MEANING_ITEM.SITE_ID 
     AND TAG.MEANING_NO = MEANING_ITEM.MEANING_NO 
    WHERE 
     TAG.SITE_ID = <site id> 
     AND TAG.NAME IN (<list of tags>) 
     AND ITEM.SITE_ID = MEANING_ITEM.SITE_ID 
     AND ITEM.ITEM_NO = MEANING_ITEM.ITEM_NO 
) 

注:我們完全可以忽略從JOIN到意義上面的查詢 - JOIN所需的所有字段已經在TAG中。

對於有所有特定標記的項目,你需要一些計算,與此類似:

SELECT * 
FROM ITEM 
WHERE <number of tags> = (
    SELECT COUNT(DISTINCT TAG_NAME) 
    FROM TAG JOIN MEANING_ITEM ON 
     TAG.SITE_ID = MEANING_ITEM.SITE_ID 
     AND TAG.MEANING_NO = MEANING_ITEM.MEANING_NO 
    WHERE 
     TAG.SITE_ID = <site id> 
     AND TAG.NAME IN (<list of tags>) 
     AND ITEM.SITE_ID = MEANING_ITEM.SITE_ID 
     AND ITEM.ITEM_NO = MEANING_ITEM.ITEM_NO 
) 

現在這個貌似很多JOIN-ING的,但這種模式是優秀的對於聚簇(又名index-organized)表和covering帶索引的查詢。

您可能需要先考慮實際StackExchange的數據量,然後再出於性能原因考慮對該設計進行非規範化(例如,刪除聯結表並限制每個項目的標記數)。

在任何情況下,在進行任何特定設計之前都要測量實際的數據量。