《自制搜索引擎》筆記(1)-書評

更新日期:

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非常類似。

 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章