Luene是一款高性能、可扩展的信息检索库,用于完成文档元信息、文档内容等搜索功能。用户可以使用Lucene 或 基于Lucene的成熟产品Nutch/Solr/Elasticsearch等来快速构建搜索服务,如文件搜索、网页搜索等。
随着信息量的爆炸式增长,人们开始发明各种各样的方案来对信息进行管理,加快信息获取速度。传统方案如新华字典中的汉语拼音音节索引及部首检字表索引、图书馆使用的杜威十进制分类法( 330.94 表欧洲经济学=330 表经济学+ .9 表地区别论述 + .04 表欧洲)等,互联网时代的方案如Windows资源管理器中的搜索功能、Google、百度等。Lucene也是互联网时代的一种方案,可用于满足大量信息检索场景:
但与Windows资源管理器、Google、百度等不同的是,Lucene并不是一个开箱即用型的服务。它面向程序开发者,是一个Java开发的、大小仅2MB左右的类库,专注于信息检索技术的文本索引和搜索功能等通用性部分,而把信息采集处理、用户交互UI、商业逻辑等业务相关性部分交给应用层。
尽管在Java世界lucene已经是标准的全文检索程序,但是C/C++世界并没有相应的工具。虽然Lucene被广泛移植到其他语言中(C/C++、C#、Python、PHP、Perl等),但其他语言版本的活跃程度一般。Xapian填补了这个缺憾,它的API和检索原理和lucene在很多方面都很相似。
Lucene另一方面,Lucene仅仅是一个Java类库,对于线上大规模使用,除了需要经过封装开发形成产品外,还需要考虑可靠性、分布式化等问题。因此出现了基于Lucene的产品化系统,例如Nutch、Solr、Elasticsearch等。
Lucene的作者Doug Cutting,同时也是Nutch、Hadoop的创始人。
下面通过构造一个简单的文本文件搜索程序,来介绍Lucene的写入(索引流程)、读取(搜索流程)等基本使用。
到这里,我们仅通过一两百行代码即完成了一个最简单的文本文件搜索功能。
正如前面的文本文件搜索程序所示,Lucene的信息检索功能主要包含两个主要流程:索引 和 搜索。这两部分的整体流程如下:
下面我们结合图例,对上述索引、搜索流程进行具体介绍。
至此,我们对Lucene的索引、查询流程有了一个直观的认识。
在3.1.3小节介绍存储索引部分时我们提到,Lucene内存中的数据最终被分为多个文件写入磁盘进行存储。这里我们先整体介绍下Lucene底层的核心存储文件,后续会结合读写流程逐一详细介绍。每个Lucene Index的核心存储文件如下图:
之前我们提到的词典表、倒排表、字段数据分别存储在上图中的segment1.tim、segment1.doc、segment1.fdt文件中。其他文件存储的数据内容可以参考下表:
文件 | 后缀 | 描述 |
---|---|---|
索引信息 | segments_n | commit point,存储当前生效的segment集合 |
写锁 | write.lock | 避免多个写类IndexWriter同时操作同一个Index |
词典表 | tim | 存储对应segment内包含的term、文档频率,按字典序排序 |
词典表索引 | tip | 每n条词典表记录抽取一条建立的稀疏索引,用于加快词典表的查找 |
倒排表 | doc | 存储每个term对应的文档id列表及其词频信息 |
位置数据 | pos | 存储term在文档中出现的位置、偏移等信息 |
数字索引 | dim | Lucene 6.0引入的、针对数字类型的新索引,通过BKD-tree structure实现,加快范围查询 |
数字二级索引 | dii | 加快PointFormat索引查找 |
字段信息 | fnm | 存储segment包含的字段名、字段类型、索引属性等信息 |
字段行存 | fdt | 以行存方式存储字段数据,通过文档id可以在fdt中获取对应文档的字段数据 |
字段行存索引 | fdx | 针对字段行存数据建立的稀疏索引,加快字段数据的定位 |
字段列存 | dvd | Lucene 4.0引入,以列存方式存储字段数据,用于加快排序、聚合等操作 |
列存元数据 | dvm | dvd文件的元数据 |
段信息 | si | 记录segment大小、版本、文件列表等元信息 |
另外,列举一个Lucene核心存储文件的实际样例,方便参考上面描述对照理解:
本文主要从整体角度介绍Lucene,通过样例程序、基本原理简介等方式建立对Lucene的直观理解。但对Lucene底层存储、主要流程实现等没有详细深入的介绍,后续我们会通过具体文章详细介绍,欢迎大家一起交流讨论。