Web数据管理论文.docx
- 文档编号:3518192
- 上传时间:2022-11-23
- 格式:DOCX
- 页数:14
- 大小:78.37KB
Web数据管理论文.docx
《Web数据管理论文.docx》由会员分享,可在线阅读,更多相关《Web数据管理论文.docx(14页珍藏版)》请在冰豆网上搜索。
Web数据管理论文
目录
1.研究背景与意义2
1.1研究背景2
1.2全文检索的意义2
2.Lucene简介3
2.1Lucene的基本介绍3
2.2Lucene的特点3
2.3 Lucene的工作方式3
2.4Lucene的相关概念4
2.5Lucene的结构5
3.Lucene索引的实现6
3.1Lucene索引原理6
3.2详细代码7
4.Lucene全文检索的实现9
4.1全文检索原理9
4.2详细代码10
4.3运行结果11
5.Lucene性能优化11
5.1 优化创建索引性能11
5.2 优化搜索性能13
6.总结15
参考文献15
基于lucene的中文检索
1.研究背景与意义
1.1研究背景
随着信息技术的不断发展,特别是互联网应用的迅速普及,电子信息以疯狂的速度每天不断增长。
目前仅Google收录的网页就超过80亿,并且每天全球互联网网页数量以千万级的数量增加。
要在如此浩瀚的信息里寻找信息,就像大海捞针一样困难。
工欲善其事,必先利其器。
要在浩瀚的网络信息海洋中自如冲浪,搜索引擎已经成为必不可少的利器。
进入21新世纪以后,随着信息多元化的增长,千篇一律的给所有用户同一个入口显然已经不能满足特定用户更深入的查询需求。
同时,这样的通用搜索引擎在目前的硬件条件下,要及时更新以得到互联网上较全面的信息是不太可能的。
针对这种情况,我们需要一个分类细致精确、数据全面深入、更新及时的面向主题的搜索引擎。
1.2全文检索的意义
在各种检索方式中全文检索作为一种面向全文、提供全文的新型检索技术,发展十分迅速,应用范围也越来越广泛,如网站内部信息的检索,用户数据库的检索等等,都有很好的应用前景。
全文检索技术是一个最普遍的信息查询应用,人们每天在网上使用Google、XX等搜索引擎查找自己所需的信息,这些搜索引擎的核心技术之一就是全文检索。
随着文档处理电子化、无纸化的发展,图书馆、新闻出版、企业甚至个人的电子数据激增,如何建立数据库、管理好自己的数据,是亟待解决的问题,而全文检索是其中一个非常实用的功能。
全文检索是指计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。
本文主要探讨的就是本文的全文检索和索引的建立的常用技术——lucene。
2.Lucene简介
2.1Lucene的基本介绍
Lucene是Apache软件基金会jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,即它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(对英文、德文等欧洲语言支持较好)。
Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎,它可以方便的嵌入到各种应用中实现针对应用的全文索引和检索功能。
2.2Lucene的特点
大部分的搜索引擎都是用B树结构来维护索引,索引的更新会导致人量的I/O操作,Lucene在实现中,对此稍微有所改进:
Lucene定义了一套以8位字节为基础的搜索文件格式,通过不断添加索引文件的测试,定期把小的索引文件合并(针对不同的更新策略,批次的大小可以调整),这样做充分利用内存减少文件的操作,提高了索引的效率。
但是Lucene在处理中文文本前要进行分词处理,而且检索结果的相关排序方面还有待完善。
2.3 Lucene的工作方式
lucene提供的服务实际包含两部分:
一入一出。
所谓入是写入,即将你提供的源(本质是字符串)写入索引或者将其从索引中删除;所谓出是读出,即向用户提供全文搜索服务,让用户可以通过关键词定位源。
2.3.1写入流程
源字符串首先经过analyzer处理,包括:
分词,分成一个个单词;去除stopword(可选)。
将源中需要的信息加入Document的各个Field中,并把需要索引的Field索引起来,把需要存储的Field存储起来。
将索引写入存储器,存储器可以是内存或磁盘。
2.3.2读出流程
用户提供搜索关键词,经过analyzer处理。
对处理后的关键词搜索索引找出对应的Document。
用户根据需要从找到的Document中提取需要的Field。
2.4Lucene的相关概念
2.4.1 analyzer
Analyzer是分析器,它的作用是把一个字符串按某种规则划分成一个个词语,并去除其中的无效词语,这里说的无效词语是指英文中的“of”、 “the”,中文中的“的”、“地”等词语,这些词语在文章中大量出现,但是本身不包含什么关键信息,去掉有利于缩小索引文件、提高效率、提高命中率。
分词的规则千变万化,但目的只有一个:
按语义划分。
这点在英文中比较容易实现,因为英文本身就是以单词为单位的,已经用空格分开;而中文则必须以某种方法将连成一片的句子划分成一个个词语。
具体划分方法下面再详细介绍,这里只需了解分析器的概念即可。
2.4.2 document
用户提供的源是一条条记录,它们可以是文本文件、字符串或者数据库表的一条记录等等。
一条记录经过索引之后,就是以一个Document的形式存储在索引文件中的。
用户进行搜索,也是以Document列表的形式返回。
2.4.3 field
一个Document可以包含多个信息域,例如一篇文章可以包含“标题”、“正文”、“最后修改时间”等信息域,这些信息域就是通过Field在Document中存储的。
Field有两个属性可选:
存储和索引。
通过存储属性你可以控制是否对这个Field进行存储;通过索引属性你可以控制是否对该Field进行索引。
这看起来似乎有些废话,事实上对这两个属性的正确组合很重要,下面举例说明:
还是以刚才的文章为例子,我们需要对标题和正文进行全文搜索,所以我们要把索引属性设置为真,同时我们希望能直接从搜索结果中提取文章标题,所以我们把标题域的存储属性设置为真,但是由于正文域太大了,我们为了缩小索引文件大小,将正文域的存储属性设置为假,当需要时再直接读取文件;我们只是希望能从搜索解果中提取最后修改时间,不需要对它进行搜索,所以我们把最后修改时间域的存储属性设置为真,索引属性设置为假。
上面的三个域涵盖了两个属性的三种组合,还有一种全为假的没有用到,事实上Field不允许你那么设置,因为既不存储又不索引的域是没有意义的。
2.4.4 term
term是搜索的最小单位,它表示文档的一个词语,term由两部分组成:
它表示的词语和这个词语所出现的field。
2.4.5 tocken
tocken是term的一次出现,它包含trem文本和相应的起止偏移,以及一个类型字符串。
一句话中可以出现多次相同的词语,它们都用同一个term表示,但是用不同的tocken,每个tocken标记该词语出现的地方。
2.4.6 segment
添加索引时并不是每个document都马上添加到同一个索引文件,它们首先被写入到不同的小文件,然后再合并成一个大索引文件,这里每个小文件都是一个segment。
2.5Lucene的结构
lucene包括core和sandbox两部分,其中core是lucene稳定的核心部分,sandbox包含了一些附加功能,例如highlighter、各种分析器。
Lucene core有七个包:
analysis,document,index,queryParser,search,store,util。
(1)Analysis:
包含一些内建的分析器,例如按空白字符分词的WhitespaceAnalyzer,添加了stopwrod过滤的StopAnalyzer,最常用的StandardAnalyzer。
(2)Document:
包含文档的数据结构,例如Document类定义了存储文档的数据结构,Field类定义了Document的一个域。
(3)Index:
包含了索引的读写类,例如对索引文件的segment进行写、合并、优化的IndexWriter类和对索引进行读取和删除操作的 IndexReader类,这里要注意的是不要被IndexReader这个名字误导,以为它是索引文件的读取类,实际上删除索引也是由它完成, IndexWriter只关心如何将索引写入一个个segment,并将它们合并优化;IndexReader则关注索引文件中各个文档的组织形式。
(4)QueryParser:
包含了解析查询语句的类,lucene的查询语句和sql语句有点类似,有各种保留字,按照一定的语法可以组成各种查询。
Lucene有很多种Query类,它们都继承自Query,执行各种特殊的查询,QueryParser的作用就是解析查询语句,按顺序调用各种 Query类查找出结果。
(5)Search:
包含了从索引中搜索结果的各种类,例如刚才说的各种Query类,包括TermQuery、BooleanQuery等就在这个包里。
(6)Store:
包含了索引的存储类,例如Directory定义了索引文件的存储结构,FSDirectory为存储在文件中的索引,RAMDirectory为存储在内存中的索引,MmapDirectory为使用内存映射的索引。
(7)Util:
包含一些公共工具类,例如时间和字符串之间的转换工具。
3.Lucene索引的实现
3.1Lucene索引原理
索引是搜索引擎的核心部分,Lucene索引采用倒排索引的数据结构在介绍搜索引擎索引结构时己经有了介绍,一下面主要说明用Lucene是如何实现建立索引的。
Lucene建立索引包含两个重要的类:
Document和Field。
Document的含义为文档,在Lucene中,它代表一种逻辑文件。
Lueene本身无法对物理文件建立索引,而只能识别并处理Document类型的文件"在某些时候,可以将每个Document与一个物理文件进行对应,用一个Document来代替一个物理文件;然而更多时候,Document和物理文件没有关系,它是作为一种数据源的集合向Lucene提供原始的要索引的文本内容。
Lucene从Document关联相应的数据源,并根据属性配置进行相应的处理。
Doeument与多个数据源关系:
图1Doeument与多个数据源关系
在Lucene中,数据源是由一个被称为Field的类来表示的。
通常情况下,可以直接通过Field的构建函数来创建一个Field类型的对象。
这个Field类型主要是用来标识当前的数据源的各种属性,存储来自数据源的数据内容。
Lucene在对多个Field进行处理时,会充分考虑到数据源的各种属性,以此做出不同的处理。
如图:
图2Lucene处理Field
3.2详细代码
FileindexDir=newFile(FILE_INDEX);
AnalyzerluceneAnalyzer=newStandardAnalyzer(Version.LUCENE_44);
IndexWriterConfigconfig=newIndexWriterConfig(Version.LUCENE_44,luceneAnalyzer);
config.setOpenMode(OpenMode.CREATE);
Directorydirectory=FSDirectory.open(indexDir);
IndexWriterindexWriter=newIndexWriter(directory,config);
FileUtils.listFile(newFile(FILE_TARGET),fileList);
for(StringfilePath:
fileList){
System.out.println("文件:
"+filePath+"正在被索引....");
Stringcontent=readFile(filePath);
Documentdoc=newDocument();
doc.add(newTextField("content",content.toString(),Store.YES));
doc.add(newTextField("path",filePath,Store.YES));
indexWriter.addDocument(doc);}
indexWriter.close();
3.3运行结果
图3需要检索的.txt目标文件
图4索引的建立
图5索引文件
4.Lucene全文检索的实现
4.1全文检索原理
在搜索引擎中,用户体验最深的就要数搜索部分了,如果这一部分的性能无法达到用户要求,那么软件就没有太大的意义了。
Lucene搜索主要是通过4个类来完成的,分别是:
Indexseareher,Query(包括子类),QueryParser,Hits。
(1)Indexsearcher:
是搜索的入口,他的search方法提供了搜索功能。
(2)Query:
有很多子类,各种不同的子类代表了不同的杳询条件。
(3)QueryParser
QueryParser是一个非常通用的帮助类,他的作用是把用户输入的文本转换为内置的Query对象(大多数web搜索引擎都提供一个杏询输入框来让用户输入查询条件)。
QueryParser内置提供了很多语法来使使用可以输入各种高级条件的Query。
比如:
Helloworld会被解析为一个AND关系的booleanQuery即,他包含两个TermQuery(Hello和world)。
也可以任意组合query string,完成复杂操作,例如“标题或正文包括lucene,并且时间在20130901到200131230之间的文章”可以表示为:
“+ (title:
lucene content:
lucene) +time:
[20130901 TO 200131230]”。
代码如下:
Directory dir = FSDirectory.getDirectory(PATH, false);
IndexSearcher is = new IndexSearcher(dir);
QueryParser parser = new QueryParser("content", new StandardAnalyzer());
Query query = parser.parse("+(title:
lucene content:
lucene) +time:
[20130901 TO 200131230]";
Hits hits = is.search(query);
for (int i = 0; i < hits.length(); i++)
{
Document doc = hits.doc(i);
System.out.println(doc.get("title");
}
is.close();
首先我们创建一个在指定文件目录上的IndexSearcher。
然后创建一个使用StandardAnalyzer作为分析器的QueryParser,它默认搜索的域是content。
接着我们用QueryParser来parse查询字串,生成一个Query。
然后利用这个Query去查找结果,结果以Hits的形式返回。
这个Hits对象包含一个列表,我们挨个把它的内容显示出来。
Lucene面向全文检索的优化在于首次索引检索后,并不把所有的记录(Document)具体内容读取出来,而是只将所有结果中匹配度最高的头100条结果(TopDocs)的lD放到结果集缓存中并返回,这里可以比较一下数据库检索:
如果是一个10000条的数据库检索结果集,数据库是一定要把所有记录内容都取得以后再开始返回给应用结果集的。
所以即使检索匹配总数很多,Lucene的结果集占用的内存空间也不会很多。
对于一般的模糊检索应用是用不到这么多的结果的,头100条已经可以满足90%以上的检索需求。
如果首批缓存结果数用完后还要读取更后面的结果时Searcher会再次检索并生成一个上次的搜索缓存数大1倍的缓存,并再重新向后抓取"所以如果构造一个Searcher去查1-120条结果,Searcher其实是进行了2次搜索过程:
头100条取完后,缓存结果用完,Searcher重新检索再构造一个200条的结果缓存,依此类推,400条缓存,800条缓存。
4.2详细代码
privatevoidsearchByKeyWords(StringkeyWords)throwsException{
IndexReaderreader=DirectoryReader.open(FSDirectory.open(newFile(FILE_INDEX)));
IndexSearchersearcher=newIndexSearcher(reader);
Analyzeranalyzer=newStandardAnalyzer(Version.LUCENE_44);
QueryParserparser=newQueryParser(Version.LUCENE_44,"content",analyzer);
Queryquery=parser.parse(keyWords);
TopDocsresults=searcher.search(query,1000);
ScoreDoc[]score=results.scoreDocs;
if(score.length==0){
System.out.println("对不起,没有找到您要的结果。
");
}else{
System.out.println("查找["+QUERY_STR+"]有"+score.length+"个结果");
for(inti=0;i try{ Documentdoc=searcher.doc(score[i].doc); System.out.print("这是第"+(i+1)+"个检索到的结果,文件名为: "); System.out.println(doc.get("path")); }catch(Exceptione){ e.printStackTrace();} } } } 4.3运行结果 通过索引文件进行检索,检索含有“的”的文件,检索结果如下(下图展示将具体内容舍去了): 图6检索结果 5.Lucene性能优化 之前所诉,我们还是在介绍Lucene以及讨论怎么样使lucene运行起来并完成指定任务。 Lucene也确实能完成大部分功能。 但是测试表明lucene的性能并不是很好,在大数据量大并发的条件下甚至会有半分钟返回的情况。 另外大数据量的数据初始化建立索引也是一个十分耗时的过程。 那么如何提高lucene的性能呢? 下面从优化创建索引性能和优化搜索性能两方面介绍。 5.1 优化创建索引性能 这方面的优化途径比较有限,IndexWriter提供了一些接口可以控制建立索引的操作,另外我们可以先将索引写入RAMDirectory,再批量写入FSDirectory,不管怎样,目的都是尽量少的文件IO,因为创建索引的最大瓶颈在于磁盘IO。 另外选择一个较好的分析器也能提高一些性能。 1、设置IndexWriter的参数优化索引建立 (1)setMaxBufferedDocs(int maxBufferedDocs) 控制写入一个新的segment前内存中保存的document的数目,设置较大的数目可以加快建索引速度,默认为10。 (2)setMaxMergeDocs(int maxMergeDocs) 控制一个segment中可以保存的最大document数目,值较小有利于追加索引的速度,默认Integer.MAX_VALUE,无需修改。 (3)setMergeFactor(int mergeFactor) 控制多个segment合并的频率,值较大时建立索引速度较快,默认是10,可以在建立索引时设置为100。 2. 通过RAMDirectory缓写提高性能 我们可以先把索引写入RAMDirectory,达到一定数量时再批量写进FSDirectory,减少磁盘IO次数。 FSDirectory fsDir = FSDirectory.getDirectory("/data/index", true); RAMDirectory ramDir = new RAMDirectory(); IndexWriter fsWriter = new IndexWriter(fsDir, new StandardAnalyzer(), true); IndexWriter ramWriter = new IndexWriter(ramDir, new StandardAnalyzer(), true); while (there are documents to index) { ... create Document ... ramWriter.addDocument(doc); if (condition for flushing memory to disk has been met) { fsWriter.addIndexes(new Directory[] { ramDir }); ramWriter.close(); ramWriter = new IndexWriter(ramDir, new StandardAnalyzer(), true); } } 3 .选择较好的分析器 这个优化主要是对磁盘空间的优化,可以将索引文件减小将近一半,相同测试数据下由600M减少到380M。 但是对时间并没有什么帮助,甚至会需要更长时间,因为较好的分析器需要匹配词库,会消耗更多CPU,测试数据用StandardAnalyzer耗时133分钟;用MMAnalyzer耗时150分钟。 5.2 优化搜索性能 虽然建立索引的操作非常耗时,但是那毕竟只在最初创建时才需要,平时只是少量的维护操作,更何况这些可以放到一个后台进程处理,并不影响用户搜索。 我们创建索引的目的就是给用户搜索,所以搜索的性能才是我们最关心的。 下面就来探讨一下如何提高搜索性能。 1.将索引放入内存 这是一个最直观的想法,因为内存比磁盘快很多。 Lucene提供RAMDirectory可以在内存中容纳索引: Directory fsDir = FSDirectory.getDirectory(“/data/index/”, false);Directory ramDir = new RAMDirectory(fsDir); Searcher searcher = new IndexSearcher(ramDir); 但是实践证明RAMDirectory和FSDirectory速度差不多,当数据量很小时两者都非常快,当数据量较大时(索引文件400M)RAMDirectory甚至比
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Web 数据管理 论文
![提示](https://static.bdocx.com/images/bang_tan.gif)