如何实现全文检索功能之搜索之路
作者:CQITer小编 时间:2018-08-22 21:21
张大胖学校的图书馆网站上线了,张大胖去浏览了一番,发现竟然没有按照关键字搜索图书的功能,大为吃惊之余,又隐约觉得机会来了: 我刚学完Web开发,其中也有数据库相关的知识,也许我可以实现这个功能啊!
想到此处,张大胖赶紧查找联系方式,抱着试试看的态度给图书馆的管理员发了一封电子邮件,表达了能实现这个搜索功能的信心和决心。

没想到真的收到回信了,管理员王老师让他在周四的下午2点半到图书馆3楼307聊一聊。
周四下午,张大胖沐浴更衣以后,如约而至。 经过一番寒暄和介绍,王老师正式进入主题:你打算怎么实现这个全文检索功能啊?
张大胖说:“我可以用SQL的 Like来实现。”
王老师笑了:“数据量小的时候Like还凑合,数据量一大,效率就非常低了。”
张大胖有点蒙:“那怎么办?”
王老师说:“得用inverted index才行。”
张大胖知道什么是index, 但是从来没有听说过inverted index,这是什么鬼?
王老师看到他迷茫的脸色,就知道这小子虽然勇气可嘉,但是技术还是有所欠缺,鼓励到:“这样吧,你回去研究研究inverted index, 然后再来实现这个全文检索功能。”
Inverted Index
张大胖灰溜溜地回到宿舍,赶紧拨号上网去查这个inverted index。
张大胖发现有很多人把他翻译成倒排索引,听起来虽然有点古怪,但实际上是一个非常简单的概念。 比如说有两篇文档:
文档1的内容:A computer is a device that can execute operations
文档2的内容:Early computers are big devices
把这两篇文章中的单词都抽取出来,并且记录下这些单词出现在哪个文档中,这就形成了一个简单粗糙的倒排索引。

通过这个“倒排索引”,只要给出一个单词,就可以迅速地定位到它在哪个文档中。 用来做全文搜素非常合适。
但是上面的倒排索引有点“粗糙”,还可以在“精化”一下。
1. 对于 a, is , to ,that ,can ,the,are 这些词对搜索来说没什么意义,用户几乎不会用他们搜索,可以过滤掉。
2. 用户搜索的时候虽然输入了computer,但是也希望搜出computers出来,所以需要把复数单词,过去式单词等做还原。
3. 用户虽然输入了device , 但是也希望搜索出Device出来,所以需要把大写都改成小写。
经过这番转换,文档1和文档2的关键字变成了这样:
文档1:[computer] [device] [execute] [operation]
文档2:[early] [computer] [big] [device]
相应地,倒排索引变成了这样:

当用户想搜索device 的时候,我们就可以告诉它,在文档1和文档2中都有。
为了更好的统计和高亮显示搜索结果,还可以记录关键词在文章中出现的次数和位置(例如:是第几个单词)

架构
明白了inverted index是怎么回事儿, 张大胖觉得只要把那些书籍的标题,介绍,作者等信息给提取出来,形成inverted index,不就可以做关键字检索了吗?
可是转眼一想,这个需求应该是个通用的需求,不仅是图书馆有,很多互联网应用,例如网上商城也需要, 我完全可以设计一个类库出来,让大家去使用啊。
张大胖迅速画出一个架构图出来:

看看,不管你是什么类型的文档,HTML, PDF, Word,甚至是数据库的数据,只要能从中抽取出文本,就可以当作我的数据源,对文本做了分析以后,就可以存入索引库。
用户可以发出各种查询,不仅仅是单个关键字,还支持关键字的组合: keyword1 AND keyword2等,对索引库进行搜索以后,把结果返回给用户。
“中间用虚线框起来的部分就是我应该实现的类库!” 张大胖对这个架构很满意。
抽象
接下来就要考虑这个类库对外提供的API了,这是个很烦人的事情。 张大胖的脑海中不由地想起来好基友Bill的谆谆教导:“软件设计就是一个不断抽象的过程。”, 关键是要抽象啊!
可是这个系统似乎有点复杂,张大胖绞尽脑汁想了两天也没有头绪,对于一个刚学会Web开发的同学,立刻就要设计类库,确实是有点勉为其难。
没办法,张大胖只好致电Bill前来帮忙。




