Lucene 研究

jopen 10年前

一、Lucene简介

Lucene是有知名全文检索/索引专家Doug Cutting采用Java语言开发的基于全文搜索的软件工具,之后贡献给Apache软件基金会做为一个开源项目,成为一个开放源代码的全文检索引擎工具包,由于他的高性能,可伸缩性而且经历了很长时间的沉淀,已经是很成熟的项目,被广泛集成于系统软件中,甚至一些商用软件也采用了Lucene做为其内部全文检索子系统的核心,如IBM的开源软件Eclipse 的帮助文档,也是采用了Lucene做 为其全文搜索引擎。Lucene 能够为文本类型的数据建立索引,所以你只要能把你要索引的数据格式转化的文本的,Lucene 就能对你的文档进行索引和搜索。比如你要对一些 HTML 文档,PDF 文档进行索引的话你就首先需要把 HTML 文档和 PDF 文档转化成文本格式的,然后将转化后的内容交给 Lucene 进行索引,然后把创建好的索引文件保存到磁盘或者内存中,最后根据用户输入的查询条件在索引文件上进行查询。不指定要索引的文档的格式也使 Lucene 能够几乎适用于所有的搜索应用程序。

下载地址:http://www.apache.org/dyn/closer.cgi/lucene/java/4.9.0

二、Lucene的优点

1、索引文件格式独立于应用平台。Lucene定义了一套以8位字节为基础的索引文件格式,使得兼容系统或者不同平台的应用能够共享建立的索引文件。

       2、在传统全文检索引擎的倒排索引的基础上,实现了分块索引,能够针对新的文件建立小文件索引,提升索引速度。然后通过与原有索引的合并,达到优化的目的。

3、优秀的面向对象的系统架构,使得对于Lucene扩展的学习难度降低,方便扩充新功能。

4、设计了独立于语言和文件格式的文本分析接口,索引器通过接受Token流完成索引文件的创立,用户扩展新的语言和文件格式,只需要实现文本分析的接口。

5、已经默认实现了一套强大的查询引擎,用户无需自己编写代码即使系统可获得强大的查询能力,Lucene的查询实现中默认实现了布尔操作、模糊查询、分组查询等等。

三、什么是全文检索

全文检索是指计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。这个过程类似于通过字典中的检索字表查字的过程。

全 文检索的方法主要分为按字检索和按词检索两种。按字检索是指对于文章中的每一个字都建立索引,检索时将词分解为字的组合。对于各种不同的语言而言,字有不 同的含义,比如英文中字与词实际上是合一的,而中文中字与词有很大分别。按词检索指对文章中的词,即语义单位建立索引,检索时按词检索,并且可以处理同义 项等。英文等西方文字由于按照空白切分词,因此实现上与按字处理类似,添加同义处理也很容易。中文等东方文字则需要切分字词,以达到按词索引的目的,关于 这方面的问题,是当前全文检索技术尤其是中文全文检索技术中的难点,在此不做详述。

四、Lucene系统结构

系统结构与源码组织图:

lucene研究

从图中我们清楚的看到,Lucene的系统由基础结构封装、索引核心、对外接口三大部分组成。其中直接操作索引文件的索引核心又是系统的重点。Lucene的将所有源码分为了7个模块(在java语言中以包即package来表示):AnalysisDocumentIndexQueryParserSearchStoreUtil.各个模块所属的系统部分也如上图所示。需要说明的是org.apache.lucene.queryPaser是做为org.apache.lucene.search的语法解析器存在,不被系统之外实际调用,因此这里没有当作对外接口看待,而是将之独立出来。

从面象对象的观点来考察,Lucene应用了最基本的一条程序设计准则:引入额外的抽象层以降低耦合性。首先,引入对索引文件的操作org.apache.lucene.store的封装,然后将索引部分的实现建立在(org.apache.lucene.index)其之上,完成对索引核心的抽象。在索引核心的基础上开始设计对外的接口org.apache.lucene.searchorg.apache.lucene.analysis。在每一个局部细节上,比如某些常用的数据结构与算法上,Lucene也充分的应用了这一条准则。在高度的面向对象理论的支撑下,使得Lucene的实现容易理解,易于扩展。

Lucene在系统结构上的另一个特点表现为其引入了传统的客户端服务器结构以外的的应用结构。Lucene可以作为一个运行库被包含进入应用本身中去,而不是做为一个单独的索引服务器存在。这自然和Lucene开放源代码的特征分不开,但是也体现了Lucene在编写上的本来意图:提供一个全文索引引擎的架构,而不是实现。

包名

功能

org.apache.lucene.analysis

语言分析器,主要用于的切词,支持中文主要是扩展此类

org.apache.lucene.document

索引存储时的文档结构管理,类似于关系型数据库的表结构

org.apache.lucene.index

索引管理,包括索引建立、删除等

org.apache.lucene.queryParser

查询分析器,实现查询关键词间的运算,如与、或、非等

org.apache.lucene.search

检索管理,根据查询条件,检索得到结果

org.apache.lucene.store

数据存储管理,主要包括一些底层的I/O操作

org.apache.lucene.util

一些公用类

Lucene主要逻辑图:

lucene研究

Lucene功能强大,但从根本上说,主要包括两块:一是文本内容经切词后索引入库;二是根据查询条件返回结果。

搜索应用程序和 Lucene 之间的关系

lucene研究

如图:用户要找Document得信息。最先将为Document文档建立Index索引。然后通过search搜索Index从而找到我们想要的内容。

首先是创建索引

索引通俗地说就是将内容做成书签目录,这样使得我们能更快地搜索得到内容。对文档建立好索引后,就可以在这些索引上面进行搜索了。搜索引擎首先会对搜索的关键词进行解析,然后再在建立好的索引上面进行查找,最终返回和用户输入的关键词相关联的文档。所以创建索引很重要。

 

五、检索流程

lucene研究

1. 索引过程:(红线)

1) 有一系列被索引文件

2) 被索引文件经过语法分析和语言处理形成一系列词(Term)。

3) 经过索引创建形成词典和反向索引表。

4) 通过索引存储将索引写入硬盘。

2. 搜索过程:(蓝线)

a) 用户输入查询语句。(Query)

b) 对查询语句经过语法分析和语言分析得到一系列词(Term)。(QueryParser和Analyzer)

c) 通过语法分析得到一个查询树。

d) 通过索引存储将索引读入到内存。(IndexWriter)

e) 利用查询树搜索索引,从而得到每个词(Term)的文档链表,对文档链表进行交,差,并得

到结果文档。

f) 将搜索到的结果文档对查询的相关性进行排序。

g) 返回查询结果给用户。

六、Lucene全文索引引擎与数据库索


 数据库

 Lucene全文索引引擎

 索引

 对于LIKE查询来说,数据传统的索引是根本用不上的。数据需要逐个便利记录进行GREP式的模糊匹配,比有索引的搜索速度要有多个数量级的下降。

 将数据源中的数据都通过全文索引一一建立反向索引

 匹配效果

 使用:like "%net%" 会把netherlands也匹配出来,

多个关键词的模糊匹配:使用like "%com%net%":就不能匹配词序颠倒的xxx.net..xxx.com

 通过词元(term)进行匹配,通过语言分析接口的实现,可以实现对中文等非英语的支持。

 匹配度

 没有匹配程度的控制:比如有记录中net出现5词和出现1次的,结果是一样的

 有匹配度算法,将匹配程度(相似度)比较高的结果排在前面。

 结果输出

 返回所有的结果集,在匹配条目非常多的时候(比如上万条)需要大量的内存存放这些临时结果集。

 通过特别的算法,将最匹配度最高的头100条结果输出,结果集是缓冲式的小批量读取的。

 可定制性

 没有接口或接口复杂,无法定制

 通过不同的语言分析接口实现,可以方便的定制出符合应用需要的索引规则(包括对中文的支持)

 结论

 使用率低,模糊匹配规则简单或者需要模糊查询的资料量少

 高负载的模糊查询应用,需要负责的模糊查询的规则,索引的资料量比较大

 

七、关于亚洲语言的的切分词问题(Word Segment)     

对于中文来说,全文索引首先还要解决一个语言分析的问题,对于英文来说,语句中单词之间是天然通过空格分开的,但亚洲语言的中日韩文语句中的字是一个字挨一个,所有,首先要把语句中按进行索引的话,这个词如何切分出来就是一个很大的问题。         首先,肯定不能用单个字符作(si-gram)为索引单元,否则查上海时,不能让含有海上也匹配。 但一句话:北京天安门,计算机如何按照中文的语言习惯进行切分呢?         “北京 天安门还是 天安门?让计算机能够按照语言习惯进行切分,往往需要机器有一个比较丰富的词库才能够比较准确的识别出语句中的单词。         另外一个解决的办法是采用自动切分算法:将单词按照2元语法(bigram)方式切分出来,比如:                 "北京天安门" ==> "北京 京天 天安 安门" 这样,在查询的时候,无论是查询"北京" 还是查询"天安门",将查询词组按同样的规则进行切分:"北京""天安安门",多个关键词之间按与"and"的关系组合,同样能够正确地映射到相应的索引中。这种方式对于其他亚洲语言:韩文,日文都是通用的。

来自:http://my.oschina.net/u/1169079/blog/288615