2008-10-24 90 views
38

我很想知道Stack Overflow的標記和搜索是如何構建的,因爲它似乎工作得很好。用於標記,雲和搜索的最佳數據體系結構(如StackOverflow)?

,如果我想要做以下所有的是一個良好的數據庫/搜索模式:

  1. 存儲標籤上的各種實體,(如何歸一化即實體,標籤和Entity_Tag表?)
    • 搜索和特定代碼
    • 建立了適用於特定搜索結果的所有標籤的標籤雲項目集
    • 如何顯示標籤列表對於搜索結果中的每個項目?

或許是有意義的標籤存儲在規範化的形式,也可作爲的#2,#4,#也許3所指的空間分隔的字符串。思考?

我聽說它說Stack Overflow使用Lucene進行搜索。真的嗎?我聽過一些討論SQL優化的播客,但沒有提到Lucene。如果他們確實使用Lucene,我想知道搜索結果有多少來自Lucene,並且「下鑽」標籤雲是否來自Lucene。

回答

5

我不知道它們是否合格,但DotNetKicks和Kigg都是開源的digg克隆實現。你可以看看他們如何做標籤和搜索。

我沒有很多的醞釀最佳猜測:)

  1. 我從來沒有像序列化多個值到一個單一領域的想法,存儲在一個字段,以便分隔字符串不吸引我...可能適用於具有樹的鄰接路徑,但這些路徑總是有序的而標籤不需要。這看起來好像會徵稅LIKE操作員的工作,你可能會找到它們。

所以我最初的看法可能是實體 - > EntityTag < - 標籤。

  1. 此方法使得通過標籤查找項目變得非常簡單,通過EntityTag連接回去,稱之爲一天。

  2. 您需要一個輔助操作來爲結果集選擇不同的標記。所以a。)拉取結果集,b。)標準化標籤空間。我認爲,不管第一個答案是什麼 - 即使將標籤填充到一個字段中仍然會產生重複標籤(並且您必須反序列化它們才能執行此操作 - 因此更多的工作,另一個完全關係的參數方法)。

  3. 還是很容易的。以下是序列化方法效果更好的一個領域。無需加入子標籤,它就在實體中。也就是說,通過兩個表連接拉出0..n標籤對我來說似乎不是太具有挑戰性。如果你正在討論perf的考慮事項,首先將它構建爲規範化,然後通過緩存或denorm進行優化。

另一種選擇是「同時做」。這感覺就像是一種過早的優化,但是您可以採用完全標準化的方法來支持任何以標籤爲中心的操作,並在持續存在序列化後在實體中擁有非標準化版本。如果還沒有完全覆蓋,還有一些工作可能會失去同步,但如果在用例中完全標準化的方式存在真正的限制,那麼兩者都是最好的。

Lucene也很有趣,你可以在索引IIRC中聲明特定的元數據,所以你也可以用這種方式來利用標籤搜索。我的懷疑是,如果你在這條路上走得太遠,那麼你最終會在數據庫中存儲的內容與某個時刻的索引之間斷開連接。我可以贊同Lucene的說法,它的功能非常強大且易於使用 - 我相信.Text將其用於搜索功能,並且在它切換到社區服務器之前支持所有的weblogs.asp.net。如果MSSQL不在圖片/足夠的範圍內,我會堅持使用全文搜索來解決數據庫中的標籤問題。

57

哇,我剛剛寫了一個大帖子,因此窒息並掛在它上面,當我點擊後退按鈕重新提交時,標記編輯器爲空。 aaargh。

所以在這裏,我又來了......

關於堆棧溢出,事實證明,他們使用SQL server 2005 full text search

關於通過@Grant推薦OS項目:

  • * DotNetKicks使用DB標記和Lucene的全文搜索。似乎沒有辦法將全文搜索與標籤搜索相結合
  • Kigg對於搜索和標籤查詢都使用Linq-to-SQL。這兩個查詢都加入了Stories-> StoryTags-> Tags。
  • 這兩個項目有3餐桌的標記,因爲大家一般似乎建議

我也發現了所以一些其他問題,我已經錯過前:

我正在爲我提到的每個項目做些什麼:

  1. 在DB中,有3個表:Entity,Tag,Entity_Tag。我用的是DB到:
    • 構建整個網站的標籤雲
    • 根據標籤瀏覽(即網址,像這樣的/questions/tagged/ASP.NET
  2. 對於搜索我利用Lucene + NHibernate。搜索
    • 標籤是concat'd到由Lucene的索引的TagString
      • 所以我有Lucene的查詢引擎的全功率(AND/OR/NOT查詢)
      • 我可以搜索文字過濾器由標籤同時
      • Lucene的分析合併的話更好的標籤搜索(即標籤搜索「測試」也將找到的東西標記爲「測試」)
    • Lucene的返回一個潛在的巨大的結果集,這是我分頁到20個結果
    • 然後NHibernate的加載憑身份證形成的實體,無論是從數據庫或實體緩存
    • 所以這是完全有可能在0點擊一個搜索結果到DB
  3. 不這樣做,但我想我可能會嘗試找到一種方法,從在Lucene中的TagString建標籤雲,而不是採取其他DB命中
  4. 沒有這樣做但也可以,但我可能會將TagString存儲在數據庫中,以便我可以顯示實體的標記列表而無需再進行2次連接。

這意味着只要一個實體的代碼修改,我必須:

  • 插入任何新標籤不存在
  • 插入/從EntityTag表中刪除
  • 更新實體.TagString
  • 更新Lucene索引的實體

鑑於在我的應用程序中讀取與寫入的比例非常大,我認爲我對此很滿意。唯一真正耗時的部分是Lucene的索引,因爲Lucene的只能插入從其索引中刪除,所以我必須要重新索引整個實體,以更新TagString。我對此並不感到興奮,但我認爲如果我在後臺線程中這樣做,那就沒問題了。

時間會告訴我們......

+0

着upmod這篇文章足以 – Shawn 2009-01-03 21:16:48

相關問題