這一節咱們來看看搜索引擎中最重要的幾個數據結構。算法
前面咱們說過索引包含正向索引和反向索引兩部分,首先咱們看看正向索引的結構。數組
正向索引用來存儲文檔的各類屬性,從邏輯上講,正向索引其實就是一個大數組,數組中每一個元素就是一個文檔的屬性集合。
若是正向索引是有Schema的,那麼它其實就相似一個關係表或者說二維數組,縱軸是文檔,橫軸是屬性;若是正向索引是Schema Free的,那麼它就相似一個Map的數組,每一個文檔都是一個Map,key是屬性名,value是屬性值。
文檔在正向索引這個大數組中的下標也是有用的,在不少搜索引擎的實現中,這個下標被稱爲文檔的邏輯ID,叫它ID是由於它惟一的標示了某個特定的文檔,叫它「邏輯」是因這個ID只在這個索引中有意義,並且文檔也許有本身的相似於ID的屬性,要避免混淆。
建立正向索引的過程極其簡單,只須要在這個大數組後面追加新的文檔便可,每次追加一個文檔就會給這個文檔產生一個新的邏輯ID。
在搜索引擎中,通常不會從正向索引中刪除任何文檔,若是須要進行刪除操做,則在每一個文檔中設立一個是否刪除的標誌,已刪除的文檔置1。數據結構
正向索引其實就這麼點東西,下面咱們來看看反向索引,這個稍微複雜點。優化
要實現關鍵字查詢,就必須有一個能夠用關鍵字找到文檔的數據結構,因此反向索引邏輯上來講就是一個字典,key是關鍵字,value就是一個文檔集。
在這裏恰好用上咱們以前在正向索引裏產生的邏輯ID,由於邏輯ID惟一的標示一個文檔,因此反向索引中的文檔集就變成了一個邏輯ID的集合,實現中固然沒這麼簡單,咱們等下再說複雜的。
固然,若是僅僅使用這樣一個結構,咱們一次只能查詢一個關鍵字,即使是做爲一個玩具來講功能也太弱了點,下面咱們來看看多關鍵字聯合查詢怎麼作。
兩個關鍵字的「聯合」,最簡單的有AND和OR兩種關係,對於AND關係,咱們須要將兩個關鍵字對應的結果集取交集;對於OR則須要取並集;多個關鍵字只需照此辦理便可。如今咱們有一個實際的問題,那就是每一個關鍵字對應的結果集可能超大,對它們求交集並集多是一個昂貴的操做,昂貴到沒法消受。
從前面說過的邏輯ID的產生規則能夠知道,邏輯ID是由小到大順序產生的,沒有重複,利用這一點咱們能夠作一些有效的優化。
首先,因爲文檔是順序進入正向索引的,因此邏輯ID在加入反向索引時保持升序,若是咱們能保持這個順序,反向索引中每一個關鍵字對應的文檔集就變成了一個有序的線性結構,AND和OR操做也就變成了兩個有序ID鏈的交和並。
回顧一下學校中關於算法和數據結構的教材,若是我沒記錯的話應該有這樣的做業題,我就不幫你們作做業了。搜索引擎
不少搜素引擎還支持過濾條件,例如日期、價格等,最簡單的方法就是,拿到反向索引匹配的結果集後,對其中的每一個文檔,在正向索引中檢查它們的屬性是否知足過濾條件,若是知足則保留,不然丟棄,最後剩下來的就是即匹配了關鍵字又知足過濾條件的文檔。索引
到目前爲止,咱們已經實現了一個最基本的全文搜索引擎,它能夠支持多關鍵字的AND/OR查詢,還能夠支持過濾條件,從功能上來講基本至關於一個玩具版Lucene :D:D文檔
從下一節開始,咱們來講說如何把目前的這個「玩具」一步步變成一個功能比較完備的產品。產品