当前位置:文档之家› lucene框架使用详解

lucene框架使用详解

Lucene框架使用详解

编写:王仁辉日期:2012/2/28

审核:日期:

批准:日期:

受控状态:是

发布版次:1.0 日期:2012/2/28

编号:01

变更记录

目录

Lucene框架使用详解 (1)

第一章概述 (3)

1.1搜索功能在现实中使用情况 (3)

第二章 lucene简介 (4)

2.1描述 (4)

2.2 理解Lucene (4)

2.2.1 Lucene是什么 (5)

2.2.2 Lucene能做什么 (5)

2.2.3 Lucene的历史 (6)

2.2.4 谁在使用Lucene (7)

2.2.5 Lucene其它版本:Perl, Python, C++, .NET, Ruby (7)

2.3索引和搜索 (7)

2.3.1什么是索引,为什么它很重要? (7)

2.3.2 什么是搜索? (8)

2.4特点及优势 (8)

第三章索引技术 (9)

3.1索引库结构—倒排序索引 (9)

3.2索引文件的检索与维护,更新是先删除后创建 (10)

3.3建立索引的执行过程(Store、Index) (10)

3.4从索引库中搜索的执行过程(QueryParser、TopDocs、ScoreDoc) (12)

第四章搜索技术(全文检索) (13)

4.1概念 (13)

4.2原理 (14)

4.3工作流程 (15)

4.4与数据库搜索的区别 (15)

第五章常用类的对象 (16)

5.1使用IndexWriter操作索引 (16)

5.1.1使用IndexWriter添加索引 (19)

5.1.2使用IndexWriter删除索引 (21)

5.1.3使用IndexWriter更新索引 (22)

5.1.4使用IndexWriter合并多个索引文件 (22)

5.2使用IndexSearcher搜索索引 (23)

5.2.1使用IndexSearcher搜索索引 (26)

5.3 IndexReader (29)

5.4 Directory (30)

5.5 Analyzer (30)

5.6 Document (30)

5.7 Field (31)

5.8 Term (32)

5.9 Query (32)

5.10 TermQuery (33)

5.11 Hits (33)

第六章lucene在项目里的集成 (33)

第一章概述

1.1搜索功能在现实中使用情况

1、Windows系统中的有搜索功能:打开“我的电脑”,按“F3”就可以使用查找的功能,查找指定的文件或文件夹。搜索的范围是整个电脑中的文件资源。

2、各种软件的帮助子系统:点击Help Help Contents,可以查找出相关的帮助信息。搜索的范围是所有帮助文件。

3、在BBS、BLOG等系统中提供的搜索文章的功能,如这里的贴吧的例子。搜索的范围是系统内的文章数据(都在数据库中)。

4、搜索引擎,如Baidu或Google等,可以查询到互联网中的网页、PDF、DOC、PPT、图片、视频等。下图是使用百度搜索的效果:

以上的查询功能都类似。都是查询的文本内容,都是相同的查询方式,即找出含有指定字符串的资源,不同的只是查询范围(分别为硬盘、所有帮助文件、数据库、互联网)。

种种迹象表明搜索功能是互联网服务的不可缺少的一部分,是优秀的资源网站的核心技术。良好的搜索体验和丰富的资源会为您的网站或软件带来超高的人气。

第二章 lucene简介

2.1描述

Lucene是apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,即它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言)。Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。

2.2 理解Lucene

Lucene流行和成功的一个关键因素是它的简单。

不同的人使用不同的方法解决相同的问题—即信息超负荷问题。一些人使用新的用户接口来工作,一些使用智能代理,还有一些使用发展较为成熟的搜索工

具如Lucene。本章稍后我们展示代码示例之前,我们将提供给你一张高层次的图来说明Lucene是什么,它不是什么和它以后会变得怎样。

2.2.1 Lucene是什么

Lucene是一个高性能、可伸缩的信息搜索(IR)库。它使你可以为你的应用程序添加索引和搜索能力。Lucene是用java实现的成熟的、免费的开源项目,是著名的Apache Jakarta大家庭的一员,并且基于在Apache软件许可 [ASF, License]。同样,Lucene是当前与近几年内非常流行的免费的Java信息搜索(IR)库。

注意:我们将使用术语IR(Information Retrieval)来描述像Lucene这样的搜索工具。人们常常将IR库归诸于搜索引擎,但是一定不要将IR库与web搜索引擎混为一谈。

正如你马上就会发现的,Lucene提供了一组简单却足够强大的核心API,只需要最小限度地理解全文索引和搜索。你只须学习它的几个类从而把Lucene集成到一个应用程序中。因为Lucene是一个Java库,它并不限定要索引和搜索的内容,这使得它比其它一些搜索程序更具有优势。

刚接触Lucene的人经常把它误解为一个现成的程序,类似文件搜索程序或web网络爬行器或是一个网

站的搜索引擎。那些都不是Lucene:Lucene是一个软件库,一个开发工具包(如果你想这样称呼),而不是一个具有完整特征的搜索应用程序。它本身

只关注文本的索引和搜索,并且这些事它完成的非常好。Lucene使得你的应用程序只针对它的问题域来处理业务规则,而把复杂的索引和搜索实现隐藏在一组简单易用的API之后。你可以把Lucene认为成一层,应用程序位于它之上,大量基于Lucene的完整的搜索程序已经构建出来。

如果你正在寻找预创建的东西或是一个抓取、文档处理和搜索的框架,请参考Lucene Wiki 的“powered by”页([color="#003366"]https://www.doczj.com/doc/8d8234533.html,/jakarta-lucene/PoweredBy)以获得更多选择:Zilverling、SearchBlox、Nutch、LARM和jSearch,还有其它一部分的命名。

2.2.2 Lucene能做什么

Lucene使你可以为你的应用程序添加索引和搜索能力(这些功能将在1.3节中描述)。Lucene可以索引并能使得可以转换成文本格式的任何数据能够被搜索。Lucene并不关心数据的来源、格式甚至它的语言,只要你能将它转换为文本。

这就意味着你可经索引并搜索存放于文件中的数据:在远程服务器上的web 页面,存于本地文件系统的文档,简单的文本文件,微软Word文档,HTML或PDF 文件或任何其它能够提取出文本信息的格式。

同样,利用Lucene你可以索引存放于数据库中的数据,提供给用户很多数据库没有提供的全文搜索的能力。一旦你集成了Lucene,你的应用程序的用户就能够像这样来搜索:+George +Rice –eat –pudding, Apple –pie +Tiger, animal:monkey AND food:banana等等。利用Lucene,你可以索引和搜索email

邮件,邮件列表档案,即时聊天记录,你的Wiki页面……等等更多。

2.2.3 Lucene的历史

Lucene最初是由Doug Cutting开发的,在SourceForge的网站上提供下载。在2001年9月做为高质量的开源Java产品加入到Apache软件基金会的Jakarta 家族中。随着每个版本的发布,这个项目得到明显的增强,也吸线了更多的用户和开发人员。2004年7月,Lucene1.4版正式发布,10月的1.4.2版本做了一次bug修正。表1.1显示了Lucene的发布历史。

表1.1 Lucene的发布历史

版本

发布日期

里程碑

0.01

2000年3月

第一个开源版本(SourceForge)

1.0

2000年10月

1.01b

2001年7月

最后的SourceForge版本

1.2

2002年6月

第一个Apache Jakarta版本

1.3

2003年12月

复合索引格式,查询分析器增加,远程搜索,token定位,可扩展的API

1.4

2004年7月

Sorting, span queries, term vectors

1.4.1

2004年8月

排序性能的bug修正

1.4.2

2004年10月

IndexSearcher optimization and misc. fixes

1.4.3

2004年冬

Misc. fixes

Lucene的创建者,Doug Cutting,在信息搜索领域有很强的理论和实践经验。他发表过许多IR主题相关的研究论文并曾在Excite、Apple和Grand Central

等公司工作。最近,考虑到web搜索引擎数目的减少和这个领域的潜在垄断,他创建了Nutch,第一个开源的万维网搜索引擎([color="#003366"]https://www.doczj.com/doc/8d8234533.html,),它用来处理抓取、索引和搜索数十亿时常更新的网页。毫不奇怪,Lucene是Nutch的核心, Doug Cutting 仍然是Lucene的后台主力,但是自从Lucene加入到Apache Jakarta的庇护之后,更多的聪明智慧注入进来。

2.2.4 谁在使用Lucene

谁不使用呢?除了在Lucene Wiki的Powered by Lucene页提到的那些组织外,还有大量的知名的跨图组织正在使用Lucene。它为Eclipse IDE、Encyclopedia Britannica CD-ROM/DVD、FedEx、Mayo Clinic、Hewlett-Packard、New Scientist杂志、Epiphany、MIT的OpenCourseware和Dspace、Akamai的EdgeComputing平台等等提供搜索能力。你的名字也将会出现在这个列表中。

2.2.5 Lucene其它版本:Perl, Python, C++, .NET, Ruby

判断一个开源软件是否成功的一种方法是通过它被改编为其它语言版本的数量。使用这个标准,Lucene是非常成功的!尽管开始时Lucene是用Java写的,Lucene已经有很多其它语言的版本了:Perl,Python,C++和.NET,并且一些基础已经用Ruby实现了。这对于那些需要访问用不同的语言写成的应用程序所得到的Lucene索引的开发者来说是个好消息。在第9章你将了解更多关于这方面的东西。

2.3索引和搜索

所有搜索引擎的核心就是索引的概念:将原始数据处理成一个高效的交差引用的查找结构以便于快速的搜索。让我们对索引和搜索过程做一次快速的高层次的浏览。

2.3.1什么是索引,为什么它很重要?

想像一下,你需要搜索大量的文件,并且你想找出包含一个指定的词或短语的文件。你如何编写一个程序来做到这个?一个幼稚的方法是针对给定的词或短语顺序扫描每个文件。这个方法有很多缺点,最明显的就是它不适合于大量的文件或者文件非常巨大的情况。这时就出现了索引:为了快速搜索大量的文本,你必须首先索引那个文本然后把它转化为一个可以让你快速搜索的格式,除去缓慢的顺序地扫描过程。这个转化过程称为索引,它的输出称为一条索引。

你可以把索引理解为一个可以让你快速随机访问存于其内部的词的数据结构。它隐含的概念类似于一本书最后的索引,可以让你快速找到讨论指定主题的页面。在Lucene中,一个索引是一个精心设计的数据结构,在文件系统中存储为一组索引文件。我们在附录B中详细地说明了索引文件的结构,但是目前你只

须认为Lucene的索引是一个能快速的词汇查找的工具。

2.3.2 什么是搜索?

搜索是在一个索引中查找单词来找出它们所出现的文档的过程。一个搜索的质量用精确度和召回率来描述。召回率衡量搜索

系统搜索到相关文档的能力,精确度衡量系统过滤不相关文档的能力。然而,在考虑搜索时你必须考虑其它一些因素。我们已经提到速度和快速搜索大量文本的能力。支持单个和多个词汇的查询,短语查询,通配符,结果分级和排序也是很重要的,在输入这些查询的时候也是友好的语法。Lucene强大的软件库提供了大量的搜索特征、bells和whistles,所以我们在搜索的时候使用lucene是很明智的。

2.4特点及优势

作为一个开放源代码项目,Lucene从问世之后,引发了开放源代码社群的巨大反响,程序员们不仅使用它构建具体的全文检索应用,而且将之集成到各种系统软件中去,以及构建Web应用,甚至某些商业软件也采用了Lucene作为其内部全文检索子系统的核心。apache软件基金会的网站使用了Lucene作为全文检索的引擎,IBM的开源软件eclipse[9]的2.1版本中也采用了Lucene作为帮助子系统的全文索引引擎,相应的IBM的商业软件Web Sphere[10]中也采用了Lucene。Lucene以其开放源代码的特性、优异的索引结构、良好的系统架构获得了越来越多的应用。

Lucene是一个高性能、可伸缩的信息搜索(IR)库。它使你可以为你的应用程序添加索引和搜索能力。Lucene是用java实现的成熟的、免费的开源项目,是著名的Apache Jakarta大家庭的一员,并且基于在Apache软件许可 [ASF, License]。同样,Lucene是当前与近几年内非常流行的免费的Java信息搜索(IR)库。

Lucene作为一个全文检索引擎,其具有如下突出的优点:

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

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

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

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

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

面对已经存在的商业全文检索引擎,Lucene也具有相当的优势。

首先,它的开发源代码发行方式(遵守Apache Software License[12]),在此基础上程序员不仅仅可以充分的利用Lucene所提供的强大功能,而且可以深入细致的学习到全文检索引擎制作技术和面相对象编程的实践,进而在此基础上根据应用的实际情况编写出更好的更适合当前应用的全文检索引擎。在这一点上,商业软件的灵活性远远不及Lucene。

其次,Lucene秉承了开放源代码一贯的架构优良的优势,设计了一个合理而极具扩充能力的面向对象架构,程序员可以在Lucene的基础上扩充各种功能,比如扩充中文处理能力,从文本扩充到HTML、PDF[13]等等文本格式的处理,编写这些扩展的功能不仅仅不复杂,而且由于Lucene恰当合理的对系统设备做了程序上的抽象,扩展的功能也能轻易的达到跨平台的能力。

最后,转移到apache软件基金会后,借助于apache软件基金会的网络平台,程序员可以方便的和开发者、其它程序员交流,促成资源的共享,甚至直接获得已经编写完备的扩充功能。

虽然Lucene使用Java语言写成,但是开放源代码社区的程序员正在不懈的将之使用各种传统语言实现(例如.net framework),在遵守Lucene索引文件格式的基础上,使得Lucene能够运行在各种各样的平台上,系统管理员可以根据当前的平台适合的语言来合理的选择。

第三章索引技术

3.1索引库结构—倒排序索引

我们需要对文档进行预处理,建立一种便于检索的数据结构,以此来提高信息检索的速度,这种数据结构就是索引。目前广泛使用的一种索引方式是倒排序索引。(说明:以下只是用于说明倒排序索引的结构,最终的索引结构要复杂的多(要考虑更多、更复杂的情况)。例如还要存储关键词在文本中的编号位置,或是首字母的字符位置等信息。)

倒排序索引的原理就如同查字典。要先查目录,得到数据对应的页码,在直接翻到指定的页码。不是在文章中找词,而是从目录中找词所在的文章。这需要在索引库中生成一个词汇表(目录),在词汇表中的每一个条记录都是类似于“词 所在文档的编号列表”的结构,记录了每一个出现过的单词,和单词出现的地方(哪些文档)。查询时先查词汇表,得到文档的编号,再直接取出相应的文档。

把数据转成指定格式放到索引库中的操作叫做建立索引。建立索引时,在把数据存到索引库后,再更新词汇表。进行搜索时,先从检索词汇表开始,然后找到相对应的文档。如果查询中仅包含一个关键词,则在词汇表中找到该单词,并取出他对应的文档就可以了。如果查询中包含多个关键词,则需要将各个单词检索出的记录进行合并再取出相应的文档记录。

如果词汇表中有一个词“传智播客”对应的文档编号列表为“1”。现在又有添加了一个包含“传智播客”的文档,则词汇表中的“传智播客”词后对应的编号列表变成了“1,2”。因为关键词的数量受实际语言的限制,所以不用担心词汇表会变的很大。

3.2索引文件的检索与维护,更新是先删除后创建

维护倒排索引有三个操作:添加、删除和更新文档。但是更新操作需要较高的代价。因为文档修改后(即使是很小的修改),就可能会造成文档中的很多的关键词的位置都发生了变化,这就需要频繁的读取和修改记录,这种代价是相当高的。因此,一般不进行真正的更新操作,而是使用“先删除,再创建”的方式代替更新操作。

3.3建立索引的执行过程(Store 、Index )

在建立索引时,先要把文档存到索引库中,还要更新词汇表。如下图:

索引库

词库

文档数据 中国的首都是哪里

中国......第1页 首都......第5页 哪里......第10页 传智播客 (11)

我们做的操作:

1、把数据对象转成相应的Document,其中的属性转为Field。

2、调用工具IndexWriter的addDocument(doc),把Document添加到索引库中。

Lucene做的操作:

1、把文档存到索引库中,并自动指定一个内部编号,用来唯一标识这条数据。内部编号类似于这条数据的地址,在索引库内部的数据进行调整后,这个编号就可能会改变,同时词汇表中引用的编号也会做相应改变,以保证正确。但我们如果在外面引用了这个编号,前后两次去取,得到的可能不是同一个文档!所以内部编号最好只在内部用。

2、更新词汇表。把文本中的词找出并放到词汇表中,建立与文档的对应关系。要把哪些词放到词汇表中呢,也就是文本中包含哪些词呢?这就用到了一个叫做Analyzer(分词器)的工具。他的作用是把一段文本中的词按规则取出所包含的所有词。对应的是Analyzer类,这是一个抽象类,切分词的具体规则是由子类实现的,所以对于不同的语言(规则),要用不同的分词器。如下图:

一段文本分词器

分词集

词典

索引库

词库

文档数据

新的文档

内容

中国……1,2

首都……2,5

哪里……6,7

传智播客…4,7

更新

新文档Document

转换AddDocument

在把对象的属性转为Field 时,相关代码为:doc.add(new Field("title", article.getTitle(), Store.YES , Index.ANALYZED ))。

是影响是否可以从这个属性中查询(No ),或是查询时可以查其中的某些词(ANALYZED ),还是要把整个内容作为一个词进行查询(NOT_ANALYZED )。

3.4从索引库中搜索的执行过程(QueryParser 、TopDocs 、ScoreDoc )

在进行搜索时,先在词汇表中查找,得到符合条件的文档编号列表。再根据文档编号真正的去取出数据(Document )。如下图:

1、把要查询字符串转为Query 对象。这就像在Hibernate 中使用HQL 查询时,也要先调用Session.createQuery(hql)转成Hibernate 的Query 对象一样。把查询字符串转换成Query 是使用QueryParser ,或使用MultiFieldQueryParser 。查询字符串也要先经过Analyzer (分词器)。要求搜索时使用的Analyzer 要与建立索引时使用的Analzyer 要一致,否则可能搜不出正确的结果。

2、调用IndexSearcher.search(),进行查询,得到结果。此方法返回值为TopDocs ,是包含结果的多个信息的一个对象。其中有totalHits 代表决记录数,

索引库

词库 文档数据 新的文档内容

中国……1,2

首都……2,5 哪里……6,7 传智播客…4,7

更新

索引

管理接

关键字

Query

转换

Search

查询

说明:只有结果信息与文档内部编号集合

Document 结果

Doc

ScoreDoc的数组。ScoreDoc是代表一个结果的相关度得分与文档编号等信息的对象。

3、取出要用到的数据列表。调用IndexSearcher.doc(scoreDoc.doc)以取出指定编号对应的Document数据。

第四章搜索技术(全文检索)

4.1概念

对于搜索,按被搜索的资源类型,分为两种:可以转为文本的、多媒体类型。搜索功能都是搜索的可以转为文本的资源(第一种)。注意,百度或谷歌提供的音乐或视频搜索不是多媒体搜索,他们是按文件名搜索。在智能手机上有一款音乐搜索的软件,可以让他听10秒钟的音乐,然后他就能上网找出这段音乐的名称、演奏者等信息。这是多媒体搜索。

按搜索的方式,搜索功能都是不处理语义,只是找出包含指定词的所有资源(只对词进行匹配)。下图就是显示“中国的首都是哪里”这个搜索要求对应的结果,可以看到,是没有“北京”这个结果的,结果页面都是出现了这些词的网页:

全文检索(Full-Text Retrieval)是指以文本作为检索对象,找出含有指定词汇的文本。全面、准确和快速是衡量全文检索系统的关键指标。

关于全文检索,我们要知道:

1、只处理文本。

2、不处理语义。

3、搜索时英文不区分大小写。

4、结果列表有相关度排序。

在信息检索工具中,全文检索是最具通用性和实用性的。 全文检索就如同ORM ,是一个概念。ORM 的框架有很多种:Hibernate 、TopLink 、iBatis 等,我们之前学习的是Hibernate 。同样的,全文检索领域中也有多种框架,Lucene 就是其中的一个用开源的全文检索框架。

Lucene 的主页为:https://www.doczj.com/doc/8d8234533.html,/。本文档中所使用的Lucene 为3.0.1的版本。以下两小节是全文检索的核心概念。

4.2原理

一般我们把检索文件存储在本地,因为如果信息检索系统在用户发出了检索请求后再去互联网上找答案,根本无法在有限的时间内返回结果。所以要先把要检索的资源集合放到本地,并使用某种特定的结构存储,称为索引,这个索引的集合称为索引库。由于索引库的结构是按照专门为快速查询设计的,所以查询的速度非常快。我们每次搜索都是在本地的索引库中进行,如下图:

图片说明:对于我们的应用程序,信息集合一般就是数据库表中的记录(文章,贴子、新闻等)或文件系统中的文件等,这些资源都可以方便、简单的获取到(使用SQL 查询或遍历文件夹)。对于搜索引擎,搜索范围是整个互联网中的资源,这些资源就需要专门的工具来获取了,我们把实现这个功能的软件叫做爬虫或蜘蛛,或称做网络机器人。爬虫在互联网上访问每一个网页并把把其中的内容传回本地服务器。

从图片上可以看出,我们不仅要搜索,还要保证数据集合与索引库的一致性。所以对于全文检索功能的开发,要做的有两个方面:索引库管理(维护索引库中

搜索引擎

搜索页面

关键字

检索工具

结果页面 结果集

Lucene 索引库

爬虫

创建索引

互联网

数据库

抓取数据

的数据)、在索引库中进行搜索。而Lucene 就是操作索引库的工具。

4.3工作流程

索引库是一个目录,里面是一些二进制文件,就如同数据库,所有的数据也

是以文件的形式存在文件系统中的。我们不能直接操作这些二进制文件,而是使用Lucene 提供的API 完成相应的操作,就像操作数据库应使用SQL 语句一样。 对索引库的操作可以分为两种:管理与查询。管理索引库使用IndexWriter ,从索引库中查询使用IndexSearcher 。Lucene 的数据结构为Document 与Field 。Document 代表一条数据,Field 代表数据中的一个属性。一个Document 中有多个Field ,Field 的值为String 型,因为Lucene 只处理文本。

我们只需要把在我们的程序中的对象转成Document ,就可以交给Lucene 管理了,搜索的结果中的数据列表也是Document 的集合。

4.4与数据库搜索的区别

全文检索不同于数据库的SQL 查询。(他们所解决的问题不一样,解决的方案也不一样,所以不应进行对比)。在数据库中的搜索就是使用SQL ,如:SELECT * FROM t WHERE content like ‘%ant%’。这样会有如下问题: a.匹配效果:如搜索ant 会搜索出planting 。这样就会搜出很多无关的信息。 b.相关度排序:查出的结果没有相关度排序,不知道我想要的结果在哪一页。我们在使用百度搜索时,一般不需要翻页,为什么?因为百度做了相关度排序:为每一条结果打一个分数,这条结果越符合搜索条件,得分就越高,叫做相关度得分,结果列表会按照这个分数由高到低排列,所以第1页的结果就是我们最想要的结果。

c.全文检索的速度大大快于SQL 的like 搜索的速度。这是因为查询方式不同造成的,以查字典举例:数据库的like 就是一页一页的翻,一行一行的找,而全文检索是先查目录,得到结果所在的页码,再直接翻到这一页。

索引管理 操作: 增加,删除,修改

Docume nt Lucene

索引库

输入

搜索 搜索接口 结果集

输出

所以数据库搜索不能替代全文检索。

第五章常用类的对象

你需要以下类来执行这个简单的索引与搜索的过程:

1、IndexWriter

2、IndexSearcher

3、IndexReader

4、Directory

5、Analyzer

6、Document

7、Field

8、Term

9、Query

10、TermQuery

11、Hits

接下来是对这些类的一个简短的浏览,针对它们在Lucene的角色,给出你粗略的概念。接下来我们开始介绍这些类。

5.1 IndexWriter

IndexWriter是在索引过程中的中心组件。这个类创建一个新的索引并且添加文档到一个已有的索引中。你可以把IndexWriter想象成让你可以对索引进行写操作的对象,但是不能让你读取或搜索。此处使用线程同步的方式确保对象的使用高效、安全和减少内存的压力。

MyIndexWriter中对IndexWriter的创建和回收:

public class MyIndexWriter {

private static Analyzer analyzer = new PaodingAnalyzer();

private static IndexWriter indexWriter;

private static ArrayList threadList = new ArrayList();

private static Directory dir = null;

private MyIndexWriter() {

}

/**

*

* @function创建indexWriter对象

* @param indexFilePath 创建索引的路径

* @param create 创建方式

* @return

* @author王仁辉

* @Create Date 2012-1-5

* @Modified By

* @Modified Date

* @why & what

*/

public static IndexWriter getInstance(String indexFilePath, boolean create) { synchronized (threadList) {

if (indexWriter == null) {

File indexFile = new File(indexFilePath);

File lockfile = new File(indexFilePath + "/write.lock");

try {

if (!indexFile.exists()) {

indexFile.mkdir();

}

dir = FSDirectory.open(indexFile);

if (IndexWriter.isLocked(dir)) {// 判断目录是否已经锁住

IndexWriter.unlock(dir);

}

if (lockfile.exists()) {

lockfile.delete();

}

if (create) {

indexWriter = new IndexWriter(dir, analyzer, true,

MaxFieldLength.UNLIMITED);

} else {

if (IndexReader.indexExists(dir)) {

indexWriter = new IndexWriter(dir, analyzer, false,

MaxFieldLength.UNLIMITED);

} else {

indexWriter = new IndexWriter(dir, analyzer, true,

MaxFieldLength.UNLIMITED);

}

}

indexWriter.setMergeFactor(1000);

indexWriter.setMaxFieldLength(Integer.MAX_VALUE);

// 控制写入一个新的segment前在内存中保存的最大的document数目

indexWriter.setRAMBufferSizeMB(32);

indexWriter.setMaxMergeDocs(200);

} catch (CorruptIndexException e) {

e.printStackTrace();

} catch (LockObtainFailedException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

} finally {

indexFile=null;

lockfile=null;

}

}

if (!threadList.contains(Thread.currentThread())) threadList.add(Thread.currentThread());

return indexWriter;

}

}

/**

*

* @function关闭indexWriter对象

* @author王仁辉

* @Create Date 2012-1-5

* @Modified By

* @Modified Date

* @why & what

*/

public static void close() {

synchronized (threadList) {

if (threadList.contains(Thread.currentThread())) threadList.remove(Thread.currentThread());

if (threadList.size() == 0) {

try {

if (indexWriter != null) {

indexWriter.optimize();

https://www.doczj.com/doc/8d8234533.html,mit();

indexWriter.close();

indexWriter = null;

}

if (dir != null) {

dir.close();

}

} catch (CorruptIndexException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

}

5.1.1使用IndexWriter添加索引

实现过程:把普通对象转换成IndexWriter需要的Documents文档对象,IndexWriter是addDocument()方法把对象索引到文件。

/**

*

* @function创建文档索引

* @param list 索引对象集合

* @author王仁辉

* @Create Date 2011-11-23

* @Modified By

* @Modified Date

* @why & what

*/

private static void createDocIndex(List list,

String indexFilePath, boolean createMode) {

try {

// System.out.println(indexFilePath);

indexWriter = MyIndexWriter.getInstance(indexFilePath + "/index",

createMode);

// 对所有的实体进行索引创建

for (SearchBean searchBean : list) {

// 建立一个lucene文档

doc = new Document();

// 搜索内容

String id = searchBean.getId();

String title = searchBean.getTitle();

String content = searchBean.getContent();

String url = searchBean.getUrl();

String keyword = searchBean.getKeyword();

String time = searchBean.getTime();

String author = searchBean.getAuthor();

String module = searchBean.getModule();

String type = searchBean.getType();

// 添加主键至文档,不分词,不高亮。

doc.add(new Field("id", id, Field.Store.YES,

Field.Index.NOT_ANALYZED, Field.TermVector.NO));

// 利用htmlparser得到处方html的纯文本

Parser parser = new Parser();

parser.setInputHTML(title);

String titleText = parser.parse(null).elementAt(0)

.toPlainTextString().trim();

// 添加到文档

doc.add(new Field("title", titleText, Field.Store.YES,

Field.Index.ANALYZED,

Field.TermVector.WITH_POSITIONS_OFFSETS));

parser.setInputHTML(content);

String contentText = parser.parse(null).elementAt(0)

.toPlainTextString().trim();

// 添加到文档

doc.add(new Field("content", contentText, Field.Store.YES, Field.Index.ANALYZED,

Field.TermVector.WITH_POSITIONS_OFFSETS));

doc.add(new Field("url", url, Field.Store.YES,

Field.Index.NOT_ANALYZED, Field.TermVector.NO));

doc.add(new Field("keyword", keyword, Field.Store.YES,

Field.Index.ANALYZED,

Field.TermVector.WITH_POSITIONS_OFFSETS));

doc.add(new Field("time", time, Field.Store.YES,

Field.Index.ANALYZED,

Field.TermVector.WITH_POSITIONS_OFFSETS));

doc.add(new Field("author", author, Field.Store.YES,

Field.Index.NOT_ANALYZED, Field.TermVector.NO));

doc.add(new Field("module", module, Field.Store.YES,

Field.Index.NOT_ANALYZED, Field.TermVector.NO));

doc.add(new Field("type", type, Field.Store.YES,

Field.Index.NOT_ANALYZED, Field.TermVector.NO));

indexWriter.addDocument(doc);

}

} catch (Exception e) {

logger.error(e.getMessage());

} finally {

MyIndexWriter.close();

}

相关主题
文本预览
相关文档 最新文档