《自制搜索引擎》笔记(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非常类似。

 


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