基于Lucene的全文检索的研究及实现
2018-07-28徐诚皓
徐诚皓
摘要:Lucene是一个基于Java 开发的,高效的、开源的全文索引引擎工具包。它使用简单,有良好的移植性,可以嵌入到各种系统及应用中。同时它也是强大的,实现了针对多种复杂文档的索引及检索。文章介绍分析了Lucene的系统结构,与关系型数据库的不同以及其实现机制,开发实现了一个基于Lucene的Web应用。
关键词:全文检索;Lucene;中文分词;Web实现
中图分类号:TP311 文献标志码:A 文章编号:1009-3044(2018)11-0095-03
Lucene是一个开源全文检索工具包,它具有优异的索引结构和良好的系统架构,提供了灵活的API函数接口和可以定制的数据存储结构,以实现具体的全文检索功能。Lucene完全由Java JDK开发而成,没有用到任何第三方开发包,因此,Lucene也具有良好的跨平台特性。文章对Lucene进行了研究和分析,以此为基础设计实现了一个手机信息检索的Web应用。
1 全文检索引擎Lucene
1.1系统结构
由于是基于Java设计的,Lucene也运用了面向对象的设计思想。首先,各种格式的文件被Lucene的对外接口导入之后,通过分析器,被转换成了一种中间索引文件,这种文件能在不同平台间兼容共享;之后,Lucene通过抽象将索引核心组成部分设计为抽象类,并提供具体平台的实现类,用于检索索引及保存结果;最后,以中间索引文件为数据源,使用某个特定平台上的方法,获得想查询的内容。此外,一些经常会使用的对象及方法,与具体平台相关的对象及方法,也封装为类,为查询提供方便。这样就使得Lucene成为了一个简单,高效,易扩展的检索引擎系统。
Lucene 由对外接口、索引核心、基础结构封装三大部分组成。系统结构图如图1 所示。
如图1所示,Lucene包含七个组成结构:
1) org.apache.lucene.analysis:语言分析器,主要用于分词
2)org.apache.lucene.document:存储索引的文档结构,类似oracle中的表结构
3) org.apache.lucene.index:索引管理,主要包括建立,删索引除等
4) org.apache.lucene.search:检索管理,提供检索方法,并根据查询条件,检索结果
5)org.apache.lucene.queryParser:查询分析器,根据关键词及其相互关系,提供自定义检索
6)org.apache.lucene.store:数据存储管理,主要包括底层I/O操作
7)org.apache.lucene.util:提供一些工具类
1.2 与关系型数据库的对比
一般来说,信息可分为结构化信息和非结构化信息。结构化信息指的是具有固定格式和长度的信息;而非结构化信息指的是不定长,无格式的信息。现实生活中,大部分信息都是非结构化的,比如HTML页面,电子邮件等。
关系型数据库,如oracle,它们在处理结构化信息时,有着高效快速的特点。但是在处理非结构化信息时,由于结构模型等原因的限制,往往力不从心。而Lucene就能夠处理这些非结构化信息,它通过将这些文本数据解析成中间格式,再进行索引查询。
1.3 检索实现机制
Lucene中有四个最基本的概念,分别是索引(index), 文档(document), 域(field)和项(term)。它们是层层包含,层层递进的。通常,一个索引,包含一些序列的文档;一个文档,包含一些序列的域;一个域,包含一些序列的项;一个项,包含一些序列的最低层的字符。项是静态存储的,这样就会使得搜索更方便,更有效率。
一般我们平时搜索文件,通常是以文件为单位,每个文件中又都记录着每个字的位置信息,进行关键字查找时,顺序扫描每个文件,找到关键字在文档中出现过几次,在什么位置,从而确定我们所需要的文件,这是索引方式中的正向索引。而Lucene使用的是索引方式中的反向索引,是以关键字为单位进行索引,找到这个关键字包含在几个文件中,记录出现的位置。反向索引机制的应用,使Lucene的检索效率更高。
1.4 中文分词
分词是文本挖掘的基础与关键。由于语言的不同特点,英文文档本身就是由一个个意思明确的英文单词组成的,而对于中文文档来说,是由一个个汉字组成的,汉字之间互相组合,又可能产生不同的语意。
所以,Lucene自带的分词器,对英文能够进行较为准确的分词,但在中文分词方面效果并不理想。为了使系统能更好地进行中文分词,处理中文信息,本文采用了IKAnalyzer作为分词器。
IKAnalyzer是一个开源的,基于Java开发的轻量级的中文分词工具包,是结合词典分词和文法分析算法的中文分词组件。它具有以下特点:1)支持中英文,数字混合分词;2)具有高速处理能力;3)能自定义用户字典;4)支持细粒度和智能分词两种切分模式。
2 手机信息检索系统的实现
本系统采用的是 MyEclipse10 + Struts2 + Tomcat6 的开发环境。
2.1 构建文本库
图2的数据是从中关村手机频道中整理的手机部分信息,包括厂商,型号,处理器,系统,内存容量,屏幕尺寸,摄像头最高像素,报价,特点等,组成以TAB分隔的tsv文件。
2.2 创建索引
一般全文检索有两个过程,创建索引和搜索索引。由此可见,索引是全文检索引擎中的关键,只有建立了索引才能进行全文检索。Lucene采用了文档(document)和域(field)来组织各种数据源。这里,我们可以把文档(document)想象成一个新闻HTML页面,把URL,新闻标题,作者,发布时间,正文等组成部分看做域(field),再根据其他配置信息,进行相应处理,创建索引。
创建索引的过程如下:
1)创建IKAnalyzer中文分词器对象,用来从文本中提取出索引项。
2)用IndexWriter类创建一个索引(index),之后为索引(index)添加文档(document)。
3)创建Document类的实例,代表我们要索引的文档(document),它是由一个或多个域(field)组成的。
4)将不同的域(field)加入到文档(document)中。比如上文提到的一个新闻HTML页面有多种信息,URL,新闻标题,作者,发布时间,正文等,都可以域用来表示。
5)IndexWriter类对象调用addDocument方法将文档(document)写到索引(index)中。
6)提交保存索引文件。
下面是建立索引的关键代码:
// 创建分词器
analyzer = new IKAnalyzer(true);
// 根据指定的路径创建索引库,如果路径不存在就会创建
directory = FSDirectory.open(new File(INDEX_PATH));
// 创建IndexWriter
IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_40, analyzer);
indexWriter = new IndexWriter(directory, config);
for (File file : fileList) {
// 读取文件的内容
List
// 创建Document对象
for (int i = 0; i < content.size(); i++) {
Document document = new Document();
//Store配置field字段是否存储到索引库
//YES:字段存储到索引库中
//No:不存储到索引库中
document.add(new TextField("contents", content.get(i), Store.YES));
// 通过IndexWriter将文档添加到索引中
indexWriter.addDocument(document);
}
}
// 提交索引
indexWriter.commit();
2.3 搜索索引
Lucene建立了功能強大的索引机制为搜索服务。
搜索索引的过程如下:
1)使用DirectoryReader将磁盘上的文件夹中索引文件信息读入到内存。
2)使用IndexSearcher创建查询对象,准备进行搜索。
3)创建IKAnalyzer对象用来对查询语句进行中文词法分析和语言处理。
4)创建MultiFieldQueryParser对象用来对查询语句进行语法分析。
5)调用MultiFieldQueryParser对象的parser方法进行语法分析,形成查询语法树,放到Query对象中。
6) 调用IndexSearcher对象的search方法,对查询语法树Query进行搜索,得到查询结果。
下面是进行搜索的关键代码:
//创建索引库
directory = FSDirectory.open(new File(INDEX_PATH));
//创建分词器
analyzer = new IKAnalyzer(true);
ireader = DirectoryReader.open(directory);
//创建查询对象
IndexSearcher isearcher = new IndexSearcher(ireader);
//要查找的关键字字符串数组
String[] stringQuery= keywords;
//Occur.MUST表示对应字段必须有查询值, Occur.MUST_NOT 表示对应字段必须没有查询值
String[] fields = new String[keywords.length];
Occur[] occ = new Occur[keywords.length];
//生成关键字与字段间的关系
for (int i = 0; i < fields.length; i++) {
fields[i] = "contents";
occ[i] = Occur.MUST;
}
//查找
Query query = MultiFieldQueryParser.parse(Version.LUCENE_40, stringQuery, fields, occ, analyzer);
//返回查到的数据
ScoreDoc[] hits = isearcher.search(query, 1000).scoreDocs;
2.4 系统演示
3 结论
Lucene全文检索机制主要工作在搜索引擎的索引阶段和检索阶段。文章对Lucene在这两个阶段的应用做了初步的探讨,实现了一个手机信息检索系统的实例。可以看出,Lucene在搜索引擎领域的应用有很大发展前景。
参考文献:
[1] 郎小伟,王申康. 基于Lucene的全文检索系统研究与开发 [J].计算机工程,2006,32(4):94-99.
[2] 管建和,甘剑峰. 基于Lucene全文检索引擎的应用研究与实现 [J].计算机工程与设计,2007,1.28(2):489-491.
[3] 向晖,郭一平,王亮. 基于Lucene的中文字典分词模块的设计与实现[J].现代图书情报技术,2006(8):46-50.
[4] 朱小杰.Lucene教程[EB/OL].[2016-03-15].https://www.cnblogs.com/zhuxiaojie/p/5277219.html#autoid-5-1-0
[5] 一枚Sir. lucene4.7 索引文件(九)[EB/OL].[2014-04-11]. https://my.oschina.net/MrMichael/blog/220961.
[6] 车东. 在应用中加入全文检索功能—基于Java的全文索引引擎Lucene简介[EB/OL].[2009.03.20]http://www.chedong.com/tech/lucene.html.
[7] 李刚,宋伟.征服Ajax+Lucene构建搜索引擎 [M].北京:人民邮电出版社,2006:220-245.
[8] 文振威,秦晓.个性化搜索引擎的研究与设计[J].计算机工程与设计,2009,30(2):342-344.