更新日期:
2017-07-28
1.基本信息
書名:自制搜索引擎
作者:[日]山田浩之,末永匡
譯者:胡屹
書籍類型:源碼剖析類
2.內容概述
本書主要講解了:如何從零開始,編寫一個基於“倒排索引(Inverted Index)”的“全文檢索引擎(FullText Search Engine)”。最終的成果,相當於一個迷你版的Apache Lucene。(注意:是自制Lucene,而不是調用Lucene)
全書大致分爲三個部分:
(1)第1章:用最簡略的語言,介紹了全文檢索引擎的基礎理論知識。
(2)第2~6章:作者專門爲本教程而編寫了一個用於教學的簡易全文檢索引擎“Wiser”(使用C語言實現)。第2~6章對這個引擎進行了細緻的源碼剖析。這個部分是全書的重點。
(3)第7章,及附錄中的“深度話題”:對Wiser引擎中沒有涉及的搜索引擎知識進行概要介紹,爲進一步深入學習搜索引擎和信息檢索打下基礎。
注:由於“全文檢索引擎”的核心是“索引”,因此Wiser引擎不包含Web爬蟲,而是對本地文本數據集進行索引和全文檢索。(Lucene檢索引擎也沒有包含Web爬蟲)
3.評價
3.1總體評價
本書的中文書名爲《自制搜索引擎》,可能讓讀者誤以爲是自制“Web搜索引擎”,其實稱爲《自制Lucene》,可能更貼切一些。
本書是目前市面上唯一一本對小型“全文檢索引擎(Full Text Search Engine)”進行深度源碼剖析的書籍。儘管源碼剖析比較辛苦,但是能學到很多課本上沒有講授的具體技術實現細節。正是這些技術實現細節,把《信息檢索》課本上各章的理論串起來,構成一個真正可運行的檢索引擎。另外,雖然書中的檢索引擎只是一個“原型系統”,但“麻雀雖小,五臟俱全”。在這個原型系統中,包含了企業級全文檢索引擎最核心的組件和算法。
除了源碼剖析之外,本書的理論講解部分寫得十分簡明易懂,使讀者能夠快速掌握全文檢索引擎最基本但也是最核心的理論。
3.2翻譯評價
翻譯質量好,且翻譯全面。書中的插圖和源代碼中的註釋都翻譯了;書中所舉的涉及日語的例子,都被轉換爲適合中文的例子;文本數據集換成了中文數據集。可以看出譯者非常用心,有認真研讀過本書,並親自測試過其中的代碼。
4.目標讀者
4.1預備知識
(1)優秀的C語言編程能力
(2)較好的《數據結構》基礎
(3)對數據庫和SQL具有初步的瞭解
4.2本書適合的讀者
1.希望自行實現一個簡易的搜索引擎。
2.對Lucene的內部實現感興趣,但苦於Lucene過於龐大,且缺乏對其源碼進行深度剖析的書籍。想找一個原型系統(附有詳盡的源碼說明和講解)做源碼剖析。
3.對百度等Web搜索引擎的內部核心原理“倒排索引”感興趣,想了解“構建索引”和“索引檢索”的技術實現細節。
4.特別提醒:源碼剖析是非常辛苦和耗時的事情。如果您的時間非常有限,那麼本書的源碼剖析部分可能不適合您。
5.閱讀建議
1.快速學習路線:如果想做一個最最簡單的全文檢索引擎,那麼只需閱讀本書的第1-4章,及附錄A-2部分,即可實現一個索引數據存儲在內存(集合)中的全文檢索引擎(不含索引數據的持久化存儲,及索引的壓縮)。覺得太簡陋了?但這就是全文檢索引擎的本質(構建索引+索引檢索)。
2.項目依賴於名爲utHash的函數庫,該函數庫提供了一系列C語言數據結構實現。準確地說,utHash不是函數庫,而是一系列宏定義,藉助於宏在C語言中實現泛型編程,效果類似於C++中的STL。項目使用了其中的哈希表(utHash)、鏈表(utList)、動態數組(utArray)、動態字符串(utString)。閱讀源碼前,需要先花些時間讀讀utHash的API手冊。
3.閱讀源碼的時候,動手繪製索引的“數據結構示意圖”,以及相關函數的“調用關係圖”(Call Graph),能夠幫助理解較難的代碼。
4.書本上沒有印出所有的代碼,只印出核心代碼。其餘代碼可以用Source Insight之類的源碼閱讀工具來輔助閱讀。
6.美中不足
1.C語言項目代碼的可讀性,確實明顯低於面向對象的Java,utHash函數庫的可讀性也低於Java集合。要是作者改爲使用Java來實現,就完美了。
2.在檢索模塊中,爲了複用構建索引時的函數,導致檢索算法相關的代碼和數據結構變得很複雜。
爲了複用構建索引時的token_to_postings_list()函數 和 inverted_index_value數據結構,編寫了複雜的遊標數據結構doc_seach_cursor、phrase_search_cursor,以及search_docs()函數和search_phrase()函數中用於構建這兩個遊標的複雜代碼。
如果檢索時不要採用“複用inverted_index_value數據結構,再加上兩種遊標”的方式,檢索代碼會清晰一些。個人想到的一種改進方法爲:把doc_seach_cursor、phrase_search_cursor和inverted_index_value合併到爲一個新的數據結構(記爲數據結構query_token_item)。在檢索時,根據inverted_index_value構建數據結構query_token_item。query_token_item定義如下:
typedef struct {
//(1)來自inverted_index_value的成員:
int token_id; /* 詞元編號(Token ID)*/
postings_list *postings_list; /* 指向包含該詞元的倒排列表的指針 */
UT_hash_handle hh; /* 用於將該結構體轉化爲哈希表 */
//(2)來自doc_search_cursor的成員:
token_positions_list *current; /* 當前的文檔編號 */
//(3)來自phrase_search_cursor的成員:
const UT_array *positions; /* 位置信息 */
int base; /* 詞元在查詢中的位置 */
int *current; /* 當前的位置信息 */
} query_token_item;
3. 檢索模塊中,“根據倒排列表求候選文檔”的算法(位於search_docs()函數中),以及“短語搜索”的算法(位於search_phrase ()函數中),雖然算法高效,但代碼可讀性很差。(而且與複雜的遊標數據結構交織在一起)
其實,這兩個算法的本質就是:對N個升序數組求交集。
4.第1版漏印的“參考文獻頁”,在出版社網站有提供下載。
7.叢書配套代碼:全文檢索引擎Wiser
相關資料
1.Github上,有人用Python實現了一個簡易的全文檢索引擎just-search-engine,其功能和組件設計與本書的Wiser非常類似。