Lucene简介及其使用
一、Lucene简介
Lucene是一个基于Java语言编写的开源全文检索工具,目前由Apache软件基金会支持。
全文检索是指搜索文档或者文档集合的一项技术。
文档可以是理解为网页、博客、推文等。搜索引擎可以理解成对网页的全文检索。用户输入的是一个query,全文检索的技术需要根据query找到最符合用户要求的文档集合,并根据相关性进行评分后将结果以排序的方式呈现出来。因此,Lucene本身提供了对非结构化文档的一般处理方法,并可以针对文档建立索引,提供快速查询、评分、排序的功能。尽管Lucene是号称全文检索工具,但针对结构化的数据的索引和插叙也是非常高效的。
Apache Lucene最初由Doug Cutting在1999年编写,该名字是其妻子的中间名以及其外祖母的first name。Lucene在2001年9月加入Apache,2005年成为Apache的顶级项目,目前稳定版本是7.5.0。
Lucene并不是一个完整的应用程序,它是一个代码库(a code library)或者说提供了一组API,可以为应用程序添加搜索的能力。
2010年Apache Solr Server成为Lucene的一个子项目。Solr是基于lucene的开源商业搜索平台,封装了常见的搜索引擎的能力,如全文检索、高亮显示、分片搜索、实时索引、动态聚类、富文本处理等。Solr也提供了索引备份和分布式搜索。Solr是以单机的全文检索服务运行的,核心使用Lucene来建立索引并提供查询的能力,它将查询的过程封装成了REST格式的HTTP/XML/JSON请求。因此,Solr可以更加快速的进行商业化运作。Solr和Lucene都是由同一个小组维护的。
二、Lucene全文检索的原理
如下图是《Lucene in Action》的一个图,解释了Lucene全文检索的工作流程。

首先,Lucene需要对源数据建立索引(index documents),然后存放到指定位置,在用户搜索的时候,需要对搜索查询进行解析,然后根据索引查找对应的数据结果,并计算得分后根据分数高低排序返回。因此,Lucene最核心的操作是建立索引以及查询的解析。
最简单的检索方式是根据用户输入的查询,去逐条比对数据库中的数据,但当查询和数据是非结构化且数据量较高的时候,这种方式非常低效。因此,我们会对数据建立索引,查询的时候则根据索引来查找对应的数据。因此,索引的建立极其重要。
全文检索的过程一般有两个主要的部分,一个是索引(indexing)一个是检索(search)。
2.1、索引
现代检索技术的索引基本上都是以倒排索引为主(Inverted Index),这种索引方法被用来存储在全文搜索下某个单词在一个文档或者一组文档中的存储位置的映射。倒排索引有两部分组成,一个是词典,一个是倒排表。词典是可以查询到的内容,倒排表是存储包含了该单词的文档集合。因此,词典的结构基本上决定了查询的速度。
在大量的数据集下,词典的建立需要考虑空间和时间的平衡,通常,内存消耗大的,检索速度也能快一点,而内存小的性能上会受影响。因此,二者的平衡机器重要。Lucene在建立索引的时候,会使用Skip-Lists数据结构将所有的索引建立在硬盘上,然后使用FST算法将索引的映射加载到内存中。FST是一个类似Map结构的数据结构,它的查询性能与HashMap差不多,甚至要慢,但是其需要的内存很小,其压缩率是HashMap的3到20倍。因此,可以加载到内存中便于查询(实际上Lucene并没有把所有的索引都加载到内存中)。
2.2、查询
Lucene是将整个索引和查询分成好多部分。如前所述,每个待查的内容都有一个倒排链,里面存储着包含了该数据的所有文档。当数据很多的时候,快速定位到这个数据及其倒排链是很重要的。在定位到倒排链之后就能查出相应的文档列表并对查询结果进行交、并操作。因此,Lucene的查询主要包括两个步骤,一个是在内存中,通过FST结构快速定位到待查数据所在的位置,找到其对应的倒排链,每个数据的倒排链都是Skip-Lists结构,接下来就是对倒排链进行交并操作,得到查询结果。

三、Lucene中基本概念
Lucene中最基本的概念包括四个:索引(index)、文档(document)、字段(field)和词项(term)。
文档-document:Lucene中的一条数据一般指一个文档(由于是全文检索起家,所以一条记录一般是指一个文档,实际中,我们也可以用结构化的一条记录来当做一个文档)。对于Lucene来说,一个文档就是有一系列字段组成的序列。
字段-field:字段可以理解为关系型数据库中的列。每一个字段是由许多个词项组成的序列。
词项-term:词项可以理解为一个单词,在lucene中,它是一个字节(bytes)的序列。注意,在不同字段中的相同的字节序列被认为是不同的词项。因此每个词项都是一个pair,即字段的名称(string)和其对应的字节序列(bytes)。Lucene对文档的存储,在底层都是以字节的形式来实现的。
索引-index:索引包含了一系列文档,是一个文档序列。
在Lucene中,字段有两种状态,一种是被存储(stored),一种是被索引(indexed)。Lucene本身有个模块(org.apache.lucene.store),它封装了一个存储层,实现了各种存储和读取文件的方案。如果一个字段被存储了,就证明它被存入到硬盘上,但是没有被索引。如果字段被倒排(inverted),那么就是被索引了,也就是说,索引的字段是被保存的同时被索引了。
Lucene并不是把所有的索引信息都存到一个文件中,它可能分成几个部分存储,每一个子索引文件被称为一个segment,不同的segment之间有合并的策略。当某个segment大小达到指定配置的时候,lucene会创建新的segment来存储索引信息。
四、Lucene索引文件及其含义
Lucene在指定路径下存储数据会生成很多个文件。每一小块的索引都是以segment为单位,维护了多个信息。主要包括:
Segment info:这个信息存储的是某个segment的元数据的信息,如文档的数量,它要使用的文件等。
Field names:字段名称信息包含了索引中使用的字段名称集合。
Stored Field values:这是保存字段内容的信息,对于每一个文档来说,都包含了一个属性-值(attribute-value pair)对的列表,其中属性是指字段名。它存储的是关于文档的额外信息,如文档的title/url/或者是指向数据库的标识符等。存储的字段集合会在搜索命中的时候返回。
Term dictionary:词典文件包含了所有的被索引的字段中的单词。词典信息中也包含了拥有某个单词的文档的数量,以及指向单词频率信息和其他信息的指针。
Term Frequency data:词频数据,包含了每个单词对应的文档数据,以及每个文档包含的这个单词的频数。如果在设置中没保存,这里就不保存文档中包含的单词频数了。
Term Proximity data:这个是存储索引中的单词在文档中的位置。这个文件不一定存在,如果你设置了擦除单词的位置信息的话。
Normalization factors:对于每个文档的每个字段,这个保存的是对应的权重,是计算相似性得分的时候度量字段重要性的。
Term Vectors:单词向量可能会存储。它包含的时候单词在文档中出现的频数信息。
Per-document values:这个存储的也是每个文档下的内容,但是会被放到内存中以快速访问。
Live documents:这是可选文件,包含的是活跃文档内容。
Point values:可选文件,记录索引字段的范围,便于范围过滤以大数值的查询。
所有属于同一个segment的文件都会有一样的名字,segment之间的区分就是用文件名中的数字来表示。下面我们列出不同后缀名对应的文件的含义。注意,如果采用压缩文件表示,那么所有的文件都会放到.cfs文件中(这是segment比较小的时候才可以)。
注意,每当有索引被保存的时候都会产生新的文件,覆盖旧的文件,也就是文件名中的数字会增加。
文件后缀名情况:
Segment File:segments_N
Lock File:write.lock:保证一次只有一个Writer可以修改索引
Segment Info:.si
Compund File:.cfs、.cfe
Fields:.fnm
Field Index:.fdx
Field Data:.fdt
Term dictionary:.tim
Term Index:.tip
Frequencies:.doc
Positions:.pos
Payloads:.pay
Norms:.nvd,.nvm
Per-document values:.dvd,.dvm
Term Vector Index:.tvx
Term Vector Data:.tvd
Live documents:.liv
Point values:.dii, .dim
参考文献:
https://en.wikipedia.org/wiki/Full-text_search
https://en.wikipedia.org/wiki/Apache_Lucene
https://en.wikipedia.org/wiki/Apache_Solr
https://zh.wikipedia.org/wiki/%E5%80%92%E6%8E%92%E7%B4%A2%E5%BC%95
http://lucene.apache.org/core/7_5_0/index.html
https://www.cnblogs.com/sessionbest/articles/8689030.html
https://zhuanlan.zhihu.com/p/35814539
https://stackoverflow.com/questions/2602253/how-does-lucene-index-documents?lq=1
https://segmentfault.com/a/1190000014480912
欢迎大家关注DataLearner官方微信,接受最新的AI技术推送
