Lucene是一个高效的基于Java的全文检索库,理解Lucene原理更容易掌握好Lucene搜索,下面我详解Lucene原理。
全文检索原理
Lucene是一个高效的基于Java的全文检索库,所以在了解Lucene之前要费一番工夫了解一下全文检索,这是Lucene原理的核心。
全文检索它的工作原理:就是是计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置。
当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式,这就是全文检索。
举一个例子:就拿新华字典做比喻,假设字典没有索引页,你要找一个字的解释你就得一页一页翻,直到找到为止,这效率可想而知。
现在有了索引页,就可以根据拼音首字母,或偏旁部首快速定位到目标字在哪一页,这个索引页,就是全文检索核心。
全文索引搜索支持非结构化数据的搜索,可以更好地快速搜索大量存在的任何单词或单词组的非结构化文本。
全文检索大体分三个过程,索引创建、索引存储、以及搜索索引。
索引创建
将现实世界中所有的结构化和非结构化数据提取信息,这个信息提取的过程,就是索引创建。
结构化和非结构化数据
1.结构化数据
结构化数据:指具有固定格式,或有限长度的数据,如数据库,元数据等。
对于结构化数据,我们一般都是可以通过关系型数据库,比如:mysql,oracle等表 的方式存储和搜索,也可以建立索引。
2.非结构化数据
非结构化数据:指不定长。或无固定格式的数据,比如:邮件,word 、pdf文档、HTML这类具有一定规则的非结构化数据。
在非结构化数据中,将一部分结构化信息抽取出来,重新组织,然后针对这部分有结构的数据,进行索引建立从而达到加速查询的目的。
比如最典型的代表,就是:Google、百度等搜索引擎按照词为单位,把HTML网页存入索引库,然后用户查询词,就会从索引库获取到想要的结果。
这种方式就构成了全文检索的基本思路,这部分从非结构化数据,比如:按照网页为单位中提取出网页标题的关键词,然后重新组织的信息,我们称之索引。
倒排索引
上面谈了全文检索技术的原理,下面谈谈全文检索技术的具体实现,绝大多数都基于倒排索引来做,所以要理解Lucene原理,需要掌握倒排索引。
要了解倒排索引,先看一下什么是正排索引。
1.正排索引
所谓正排索引,就是以文档对象的唯一 ID 作为索引,以文档内容作为记录,和我们人脑的记忆更加贴合的一种数据结构。
举一个生活中的例子:记忆古诗,当别人问我们《静夜思》这首诗的时候,我们很容易就能够背出完整的诗句。
但是如果有人问我们哪一首诗里面,包含有霜这个字的时候,我们就很难想到《静夜思》这首诗了,因为我们的大脑在记忆古诗的时候是建立了一个正排索引。
正排索引就是:输入静夜思,然后出现“窗前明月光,疑是地上霜,举头望明月,低头思故乡”,大脑记忆古诗的这个顺序,这就是正排索引。
2.倒排索引
而倒排索引是与这样的数据结构相反的,有一个从古代流传至今的游戏,叫做《飞花令》,规则就是要能够说出含有“花”的诗句,谁能够说的多谁就获胜。
倒排索引就是当用户在搜索引擎搜索框中输入关键词的时候,搜索引擎就会把和关键词有关的页面展现给用户,而这个过程就叫做倒排索引,这个与上面诗句的例子类似。
倒排索引是将文档内容中的单词作为索引,将包含该词的文档 ID 作为记录。
如下图所示:
举一个例子,手机查询,原始数据如下:
doc_id |
name |
desc |
匹配数(在分词表中出现) |
1 |
华为手机 |
中国第一品牌 |
2 |
2 |
华为荣耀手机 |
年轻人用的手机 |
3 |
3 |
荣耀手机 |
….. |
2 |
4 |
青春版手机 |
….. |
1 |
5 |
P40手机 |
….. |
1 |
然后,通过分词产生倒排索引表,如下所示:
分词 |
doc_ids |
华为 |
[1,2] |
手机 |
[1,2,3,4,5] |
荣耀 |
[2,3] |
青春版 |
[4] |
P40 |
[5] |
倒排索引进行分组,根据’华为’、’荣耀’、’手机’分组,这就是倒排索引。
倒排索引和正排索引的区别
正排索引是通过文档找单词,既key找value,倒排索引是通过单词找文档,既value找key,这就是两者最大的区别。
倒排索引到此也就讲清楚了,你只要理解了倒排索引这个过程,对搜索引擎就有一个整体的了解了。
索引存储
索引创建好后,下一步就是索引存储。
以 Lucene为例,Lucene 的存储结构,如下图所示:
从大到小是:Index -> Segment -> Doc -> Field -> Term,类比 MySQL 为 Database -> Table -> Record -> Field -> Value。
搜索索引
理解了索引的创建过程,最后一步就是搜索索引的查询。
查询索引做了哪些事情?
查询索引主要分为如下4大步骤:
第一步:对查询内容进行词法分析
举个例子,用户输入语句:lucene AND learned NOT hadoop,说明用户想找一个包含lucene和learned,然而不包括hadoop的文档。
这里的AND以及NOT这些分析,这就是词法和语法分析,类似关系数据库oracle、mysql中sql的意义。
第二步:搜索索引
搜索索引:就是去索引库中找到满足查询条件的索引列表。
这里大致分为如下3步:
首先:在反向索引表中,分别找出包含lucene,learn,hadoop的文档链表。
其次:对包含lucene,learn的链表进行合并操作,得到既包含lucene又包含learn的文档链表。
最后:将此链表与hadoop的文档链表进行差操作,去除包含hadoop的文档,从而得到既包含lucene又包含learn而且不包含hadoop的文档链表。
第三步:内容排序
计算权重对返回内容排序,影响一个词(Term)在一篇文档中的重要性主要有两个因素:
Term Frequency (tf):即此Term在此文档中出现了多少次,tf 越大说明越重要。
Document Frequency (df):即有多少文档包含次Term,df 越大说明越不重要。
Lucene原理总结
最后配一张图来加强下对创建索引和查询索引的理解:
首先通过分词,通过词法分析索引创建,然后索引存储,最后搜索索引查询,这就是Lucene原理。
陈睿mikechen
10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。
关注「mikechen」公众号,获取更多技术干货!
后台回复【面试】即可获取《史上最全阿里Java面试题总结》,后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》