2012-03-15 120 views
2

假設我正在尋找識別文檔的多個頁面(可能大約有500多頁)中某個詞的所有出現次數。我已經完成了發現單詞出現在哪些頁面上的工作。例如,我想列出計算機單詞出現的所有頁面。文檔詞索引數據庫結構?

什麼是最好的方式來存儲這些數據,以便通過網絡服務快速搜索?我的直覺是,只是這樣做:

表結構: VARCHAR(30)WORD,一滴PAGES

而且具有地方發生的話,然後就網頁場是所有頁面的一個逗號分隔的列表當查詢匹配WORD字段時,將其展開並列出所有頁面。我想知道是否有更高效的方法來達到這個目的?我可能會使用MySQL和PHP/Zend,因爲這是我最熟悉的。但如果你有更好的想法,我肯定會開放的聽取他們的意見。

表格可能會變得非常長,因爲我需要爲文檔中的每個獨特單詞添加一行。也許我會設定一個不超過3或4個字符的限制,但我仍然可以想象10萬字以上的字。如果按字母順序排列行列表,可以以某種方式使我的數據庫服務器更容易嗎? (即蘋果,蘋果,分支按升序排列?)MySQL可以處理這個問題嗎?其他的東西可以更好地處理嗎?

最後,有沒有更好的結構模式,可能以後讓我收集/提供有趣的數據? (即給用戶相關的詞經常出現在附近等)

回答

4

你將不得不正常化你的數據庫。

首先存儲

table pages (
    id unsigned integer auto_increment primary key, 
    page blob, 
    other_interesting_data_about_a_page) 

頁然後一個表來保存這個詞表統計

table wc (
    id unsigned integer auto_increment primary key 
    word varchar(20) unique key, 
    count unsigned integer default 1, 
    other_interesting_data_about_a_word....) 

然後一個表的話鏈接到

table word_page (
    word_id unsigned integer, 
    page_id unsiged integer, 
    pos_in_page unsigned integer, /*position*/ 
    primary key pk (word_id, page_id, pos_in_page)) 

頁現在你可以查詢頁面中單詞的數量:

SELECT COUNT(*) 
FROM word_page 
WHERE page_id = 123 

或者單詞'the'在頁面中重複的次數。

SELECT COUNT(*) 
FROM word_page wp 
INNER JOIN wc ON (wp.word_id = wc.id) 
WHERE wp.page_id = 123 AND wc.word = 'the' 

警告

而且具有頁面場將所有的頁面的逗號分隔列表的話.....

永遠不使用CSV在一個數據庫,這是你可以使用的最糟糕的反模式,如果你爲此付出,它會一遍又一遍地咬你。
如果你覺得有必要,可以在頭部踢自己,直到衝動消失,然後使用一兩張單獨的桌子。

+0

我永遠不會在數據庫中使用CSV。 :)謝謝你的提示! – Emeka 2012-03-16 19:30:54

1

更容易維護和索引,我會成立一個映射表與計算primarey鍵: ID BIGINT AUTO_INCREMENT, 字VARCHAR(30), 頁INT, ... 並建立兩個索引單詞和頁面。 這樣,你就更加靈活,不需要分解列表甚至可以訪問一些統計信息(哪些頁面使用更多獨特的單詞等)。

MySQL(和其他所有關係數據庫引擎)使用樹結構構建自己的內部索引,因此不需要預先對數據進行排序。

這張表很容易被MySQL處理。可能還有更快的其他數據庫引擎,但這是一個好的開始。

當然你可以添加更多的表格,也就是word,other_word,distance,這一切都取決於你的規範和解析器的可能性。

,如果你有一些時間來瀏覽一下,看看如何searchengines,例如Solr的/ Lucene的正在處理這個事情

+0

感謝Solr/Lucene的提示。可能最終會朝着這個方向前進! – Emeka 2012-03-16 19:30:07

3

與之相對標準化,這是通用的,而是相當不錯的實踐空間,效率低下這個特定的問題,你可能想要堅持你的結構,但用位向量(仍在blob列內)替換blob中的頁面列表,每個位代表一個頁面。優點是對於500頁,即使該單詞出現在所有頁面(500/8 = 62.5)中,該矢量對於一個單詞的最大大小也將是63個字節。

在位域內,每個頁面對應一個位數:如果位數N爲ON,則表示該單詞出現在頁面N,否則它不出現在頁面N. 這是基本上由DBIx SQL text indexing implementation使用 位從右到左進行編號,並且可以刪除非顯着的0。

例如,如果單詞「計算機」出現在第3,4和12頁中,值將爲:二進制(= 2060,十進制表示)中的 100000001100

如果它只出現在第400頁,它將是數字1,然後是399 0's。如果它出現在每個頁面上,則該值將是數字1的500倍。

我一直在用postgresql數據庫中的全文索引郵件內容來表示(加上分區),我發現它的擴展性非常好,與天真的規範化實現相反,小數據集。

+0

永遠不會考慮這樣的事情,謝謝!我認爲Johan的答案雖然成本更高,但可以讓我用存儲的數據做更有趣的事情。 – Emeka 2012-03-16 19:21:06

+1

@Emeka(以及),不錯的想法大衛,但不要在**遇到速度/空間問題之前不要被壓制**。我想知道你如何處理在頁面上多次出現的單詞(但現在我陷入了過深)。 – Johan 2012-03-16 20:07:52