luceneWord文件下载.docx
- 文档编号:6902656
- 上传时间:2023-05-07
- 格式:DOCX
- 页数:18
- 大小:29.81KB
luceneWord文件下载.docx
《luceneWord文件下载.docx》由会员分享,可在线阅读,更多相关《luceneWord文件下载.docx(18页珍藏版)》请在冰点文库上搜索。
记录==>
字段,所以很多传统的应用的文件、数据库等都可以比较方便的映射到Lucene的存储结构/接口中。
总体上看:
可以先把Lucene当成一个支持全文索引的数据库系统。
比较一下Lucene和数据库:
Lucene
数据库
索引数据源:
doc(field1,field2...)doc(field1,field2...)
\indexer/
_____________
|LuceneIndex|
--------------
/searcher\
结果输出:
Hits(doc(field1,field2)doc(field1...))
索引数据源:
record(field1,field2...)record(field1..)
\SQL:
insert/
|DBIndex|
-------------
/SQL:
select\
结果输出:
results(record(field1,field2..)record(field1...))
Document:
一个需要进行索引的“单元”
一个Document由多个字段组成
Record:
记录,包含多个字段
Field:
字段
Hits:
查询结果集,由匹配的Document组成
RecordSet:
查询结果集,由多个Record组成
全文检索≠like"
%keyword%"
通常比较厚的书籍后面常常附关键词索引表(比如:
北京:
12,34页,上海:
3,77页……),它能够帮助读者比较快地找到相关内容的页码。
而数据库索引能够大大提高查询的速度原理也是一样,想像一下通过书后面的索引查找的速度要比一页一页地翻内容高多少倍……而索引之所以效率高,另外一个原因是它是排好序的。
对于检索系统来说核心是一个排序问题。
由于数据库索引不是为全文索引设计的,因此,使用like"
时,数据库索引是不起作用的,在使用like查询时,搜索过程又变成类似于一页页翻书的遍历过程了,所以对于含有模糊查询的数据库服务来说,LIKE对性能的危害是极大的。
如果是需要对多个关键词进行模糊匹配:
like"
%keyword1%"
andlike"
%keyword2%"
...其效率也就可想而知了。
所以建立一个高效检索系统的关键是建立一个类似于科技索引一样的反向索引机制,将数据源(比如多篇文章)排序顺序存储的同时,有另外一个排好序的关键词列表,用于存储关键词==>
文章映射关系,利用这样的映射关系索引:
[关键词==>
出现关键词的文章编号,出现次数(甚至包括位置:
起始偏移量,结束偏移量),出现频率],检索过程就是把模糊查询变成多个可以利用索引的精确查询的逻辑组合的过程。
从而大大提高了多关键词查询的效率,所以,全文检索问题归结到最后是一个排序问题。
由此可以看出模糊查询相对数据库的精确查询是一个非常不确定的问题,这也是大部分数据库对全文检索支持有限的原因。
Lucene最核心的特征是通过特殊的索引结构实现了传统数据库不擅长的全文索引机制,并提供了扩展接口,以方便针对不同应用的定制。
可以通过一下表格对比一下数据库的模糊查询:
Lucene全文索引引擎
索引
将数据源中的数据都通过全文索引一一建立反向索引
对于LIKE查询来说,数据传统的索引是根本用不上的。
数据需要逐个便利记录进行GREP式的模糊匹配,比有索引的搜索速度要有多个数量级的下降。
匹配效果
通过词元(term)进行匹配,通过语言分析接口的实现,可以实现对中文等非英语的支持。
使用:
like"
%net%"
会把netherlands也匹配出来,
多个关键词的模糊匹配:
使用like"
%com%net%"
:
就不能匹配词序颠倒的
匹配度
有匹配度算法,将匹配程度(相似度)比较高的结果排在前面。
没有匹配程度的控制:
比如有记录中net出现5词和出现1次的,结果是一样的。
结果输出
通过特别的算法,将最匹配度最高的头100条结果输出,结果集是缓冲式的小批量读取的。
返回所有的结果集,在匹配条目非常多的时候(比如上万条)需要大量的内存存放这些临时结果集。
可定制性
通过不同的语言分析接口实现,可以方便的定制出符合应用需要的索引规则(包括对中文的支持)
没有接口或接口复杂,无法定制
结论
高负载的模糊查询应用,需要负责的模糊查询的规则,索引的资料量比较大
使用率低,模糊匹配规则简单或者需要模糊查询的资料量少
全文检索和数据库应用最大的不同在于:
让最相关的头100条结果满足98%以上用户的需求
Lucene的创新之处:
大部分的搜索(数据库)引擎都是用B树结构来维护索引,索引的更新会导致大量的IO操作,Lucene在实现中,对此稍微有所改进:
不是维护一个索引文件,而是在扩展索引的时候不断创建新的索引文件,然后定期的把这些新的小索引文件合并到原先的大索引中(针对不同的更新策略,批次的大小可以调整),这样在不影响检索的效率的前提下,提高了索引的效率。
Lucene和其他一些全文检索系统/应用的比较:
其他开源全文检索系统
增量索引和批量索引
可以进行增量的索引(Append),可以对于大量数据进行批量索引,并且接口设计用于优化批量索引和小批量的增量索引。
很多系统只支持批量的索引,有时数据源有一点增加也需要重建索引。
数据源
Lucene没有定义具体的数据源,而是一个文档的结构,因此可以非常灵活的适应各种应用(只要前端有合适的转换器把数据源转换成相应结构),
很多系统只针对网页,缺乏其他格式文档的灵活性。
索引内容抓取
Lucene的文档是由多个字段组成的,甚至可以控制那些字段需要进行索引,那些字段不需要索引,近一步索引的字段也分为需要分词和不需要分词的类型:
需要进行分词的索引,比如:
标题,文章内容字段
不需要进行分词的索引,比如:
作者/日期字段
缺乏通用性,往往将文档整个索引了
语言分析
通过语言分析器的不同扩展实现:
可以过滤掉不需要的词:
antheof等,
西文语法分析:
将jumpsjumpedjumper都归结成jump进行索引/检索
非英文支持:
对亚洲语言,阿拉伯语言的索引支持
缺乏通用接口实现
查询分析
通过查询分析接口的实现,可以定制自己的查询语法规则:
比如:
多个关键词之间的+-andor关系等
并发访问
能够支持多用户的使用
关于亚洲语言的的切分词问题(WordSegment)
对于中文来说,全文索引首先还要解决一个语言分析的问题,对于英文来说,语句中单词之间是天然通过空格分开的,但亚洲语言的中日韩文语句中的字是一个字挨一个,所有,首先要把语句中按“词”进行索引的话,这个词如何切分出来就是一个很大的问题。
首先,肯定不能用单个字符作(si-gram)为索引单元,否则查“上海”时,不能让含有“海上”也匹配。
但一句话:
“北京天安门”,计算机如何按照中文的语言习惯进行切分呢?
“北京天安门”还是“北京天安门”?
让计算机能够按照语言习惯进行切分,往往需要机器有一个比较丰富的词库才能够比较准确的识别出语句中的单词。
另外一个解决的办法是采用自动切分算法:
将单词按照2元语法(bigram)方式切分出来,比如:
"
北京天安门"
==>
北京京天天安安门"
。
这样,在查询的时候,无论是查询"
北京"
还是查询"
天安门"
,将查询词组按同样的规则进行切分:
"
,"
天安安门"
,多个关键词之间按与"
and"
的关系组合,同样能够正确地映射到相应的索引中。
这种方式对于其他亚洲语言:
韩文,日文都是通用的。
基于自动切分的最大优点是没有词表维护成本,实现简单,缺点是索引效率低,但对于中小型应用来说,基于2元语法的切分还是够用的。
基于2元切分后的索引一般大小和源文件差不多,而对于英文,索引文件一般只有原文件的30%-40%不同,
自动切分
词表切分
实现
实现非常简单
实现复杂
查询
增加了查询分析的复杂程度,
适于实现比较复杂的查询语法规则
存储效率
索引冗余大,索引几乎和原文一样大
索引效率高,为原文大小的30%左右
维护成本
无词表维护成本
词表维护成本非常高:
中日韩等语言需要分别维护。
还需要包括词频统计等内容
适用领域
嵌入式系统:
运行环境资源有限
分布式系统:
无词表同步问题
多语言环境:
对查询和存储效率要求高的专业搜索引擎
目前比较大的搜索引擎的语言分析算法一般是基于以上2个机制的结合。
关于中文的语言分析算法,大家可以在Google查关键词"
wordsegmentsearch"
能找到更多相关的资料。
安装和使用
下载:
注意:
Lucene中的一些比较复杂的词法分析是用JavaCC生成的(JavaCC:
JavaCompilerCompiler,纯Java的词法分析生成器),所以如果从源代码编译或需要修改其中的QueryParser、定制自己的词法分析器,还需要从
lucene的组成结构:
对于外部应用来说索引模块(index)和检索模块(search)是主要的外部应用入口
org.apache.Lucene.search/
搜索入口
org.apache.Lucene.index/
索引入口
org.apache.Lucene.analysis/
语言分析器
org.apache.Lucene.queryParser/
查询分析器
org.apache.Lucene.document/
存储结构
org.apache.Lucene.store/
底层IO/存储结构
org.apache.Lucene.util/
一些公用的数据结构
简单的例子演示一下Lucene的使用方法:
索引过程:
从命令行读取文件名(多个),将文件分路径(path字段)和内容(body字段)2个字段进行存储,并对内容进行全文索引:
索引的单位是Document对象,每个Document对象包含多个字段Field对象,针对不同的字段属性和数据输出的需求,对字段还可以选择不同的索引/存储字段规则,列表如下:
方法
切词
存储
用途
Field.Text(Stringname,Stringvalue)
Yes
切分词索引并存储,比如:
标题,内容字段
Field.Text(Stringname,Readervalue)
No
切分词索引不存储,比如:
META信息,
不用于返回显示,但需要进行检索内容
Field.Keyword(Stringname,Stringvalue)
不切分索引并存储,比如:
日期字段
Field.UnIndexed(Stringname,Stringvalue)
不索引,只存储,比如:
文件路径
Field.UnStored(Stringname,Stringvalue)
只全文索引,不存储
publicclassIndexFiles{
//使用方法:
:
IndexFiles[索引输出目录][索引的文件列表]...
publicstaticvoidmain(String[]args)throwsException{
StringindexPath=args[0];
IndexWriterwriter;
//用指定的语言分析器构造一个新的写索引器(第3个参数表示是否为追加索引)
writer=newIndexWriter(indexPath,newSimpleAnalyzer(),false);
for(inti=1;
i<
args.length;
i++){
System.out.println("
Indexingfile"
+args[i]);
InputStreamis=newFileInputStream(args[i]);
//构造包含2个字段Field的Document对象
//一个是路径path字段,不索引,只存储
//一个是内容body字段,进行全文索引,并存储
Documentdoc=newDocument();
doc.add(Field.UnIndexed("
path"
args[i]));
doc.add(Field.Text("
body"
(Reader)newInputStreamReader(is)));
//将文档写入索引
writer.addDocument(doc);
is.close();
};
//关闭写索引器
writer.close();
}
}
索引过程中可以看到:
∙语言分析器提供了抽象的接口,因此语言分析(Analyser)是可以定制的,虽然lucene缺省提供了2个比较通用的分析器SimpleAnalyser和StandardAnalyser,这2个分析器缺省都不支持中文,所以要加入对中文语言的切分规则,需要修改这2个分析器。
∙Lucene并没有规定数据源的格式,而只提供了一个通用的结构(Document对象)来接受索引的输入,因此输入的数据源可以是:
数据库,WORD文档,PDF文档,HTML文档……只要能够设计相应的解析转换器将数据源构造成成Docuement对象即可进行索引。
∙对于大批量的数据索引,还可以通过调整IndexerWrite的文件合并频率属性(mergeFactor)来提高批量索引的效率。
检索过程和结果显示:
搜索结果返回的是Hits对象,可以通过它再访问Document==>
Field中的内容。
假设根据body字段进行全文检索,可以将查询结果的path字段和相应查询的匹配度(score)打印出来,
publicclassSearch{
StringindexPath=args[0],queryString=args[1];
//指向索引目录的搜索器
Searchersearcher=newIndexSearcher(indexPath);
//查询解析器:
使用和索引同样的语言分析器
Queryquery=QueryParser.parse(queryString,"
newSimpleAnalyzer());
//搜索结果使用Hits存储
Hitshits=searcher.search(query);
//通过hits可以访问到相应字段的数据和查询的匹配度
for(inti=0;
hits.length();
System.out.println(hits.doc(i).get("
)+"
;
Score:
+
hits.score(i));
在整个检索过程中,语言分析器,查询分析器,甚至搜索器(Searcher)都是提供了抽象的接口,可以根据需要进行定制。
HackingLucene
简化的查询分析器
个人感觉lucene成为JAKARTA项目后,画在了太多的时间用于调试日趋复杂QueryParser,而其中大部分是大多数用户并不很熟悉的,目前LUCENE支持的语法:
Query:
=(Clause)*
Clause:
=["
+"
"
-"
][<
TERM>
](<
|"
("
Query"
)"
)
中间的逻辑包括:
andor+-&
&
||等符号,而且还有"
短语查询"
和针对西文的前缀/模糊查询等,个人感觉对于一般应用来说,这些功能有一些华而不实,其实能够实现目前类似于Google的查询语句分析功能其实对于大多数用户来说已经够了。
所以,Lucene早期版本的QueryParser仍是比较好的选择。
添加修改删除指定记录(Document)
Lucene提供了索引的扩展机制,因此索引的动态扩展应该是没有问题的,而指定记录的修改也似乎只能通过记录的删除,然后重新加入实现。
如何删除指定的记录呢?
删除的方法也很简单,只是需要在索引时根据数据源中的记录ID专门另建索引,然后利用IndexReader.delete(Termterm)方法通过这个记录ID删除相应的Document。
根据某个字段值的排序功能
lucene缺省是按照自己的相关度算法(score)进行结果排序的,但能够根据其他字段进行结果排序是一个在LUCENE的开发邮件列表中经常提到的问题,很多原先基于数据库应用都需要除了基于匹配度(score)以外的排序功能。
而从全文检索的原理我们可以了解到,任何不基于索引的搜索过程效率都会导致效率非常的低,如果基于其他字段的排序需要在搜索过程中访问存储字段,速度回大大降低,因此非常是不可取的。
但这里也有一个折中的解决方法:
在搜索过程中能够影响排序结果的只有索引中已经存储的docID和score这2个参数,所以,基于score以外的排序,其实可以通过将数据源预先排好序,然后根据docID进行排序来实现。
这样就避免了在LUCENE搜索结果外对结果再次进行排序和在搜索过程中访问不在索引中的某个字段值。
这里需要修改的是IndexSearcher中的HitCollector过程:
...
scorer.score(newHitCollector(){
privatefloatminScore=0.0f;
publicfinalvoidcollect(intdoc,floatscore){
if(score>
0.0f&
//ignorezeroedbuckets
(bits==null||bits.get(doc))){//skipdocsnotinbits
totalHits[0]++;
=minScore){
/*原先:
Lucene将docID和相应的匹配度score例入结果命中列表中:
*hq.put(newScoreDoc(doc,score));
//updatehitqueue
*如果用doc或1/doc代替score,就实现了根据docID顺排或逆排
*假设数据源索引时已经按照某个字段排好了序,而结果根据docID排序也就实现了
*针对某个字段的排序,甚至可以实现更复杂的score和docID的拟合。
*/
hq.put(newScoreDoc(doc,(float)1/doc));
if(hq.size()>
nDocs){//ifhitqueueoverfull
hq.pop();
//removelowestinhitqueue
minScore=((ScoreDoc)hq.top()).score;
//resetminScore
},reader.maxDoc());
更通用的输入输出接口
虽然lucene没有定义一个确定的输入文档格式,但越来越多的人想到使用一个标准的中间格式作为Lucene的数据导入接口,然后其他数据,比如PDF只需要通过解析器转换成标准的中间格式就可以进行数据索引了。
这个中间格式主要以XML为主,类似实现已经不下4,5个:
数据源:
WORDPDFHTMLDBother
\|||/
XML中间格式
|
LuceneINDEX
目前还没有针对MSWord文档的解析器,因为Word文档和基于ASCII的RTF文档不同,需要使用COM对象机制解析。
这个是我在Google上查的相关资料:
另外一个办法就是把Word文档转换成text:
//www
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- lucene