[转]Lucene经验总结 (转注:较旧,但有干货)

Posted 麦仲肥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[转]Lucene经验总结 (转注:较旧,但有干货)相关的知识,希望对你有一定的参考价值。

// 转自:http://zdm2008.blog.163.com/blog/static/20491545200971894520912/

 

个人的一点经验,分享之佘,还请大家补充!!

如果你想学Lucene,那么Sphinx你一定不能放过

------------------------------------------------------------------------------------------------------------

搜索引擎知识总结

1:搜索引擎按原理和工作方式可分为:

A:爬虫式,主要用Socket实现,基于TCP/IP协议

B:目录索引式,以早期的yahoo为代表

C:元搜索引擎,即将多个搜索引擎的结果合并返回

 

2:按领域范围可分为:

A:通用搜索引擎---针对全互联网全部网站和各种数据信息,信息全,领域广

B:垂直搜索引擎---针对果某一行业,如企业库搜索,供求信息搜索,房产搜索等

 

3:信息类型分类:

二进制的文档,音频,视频,图片等。其中常见的二进制文档有:TXT,WORD,EXCEL,PPT,PDF,XML,html

 

5:搜索引擎研究网站

A:数据挖掘研究院---http://www.dmresearch.net

B:哈工大语言技术网---http://www.langtech.org.cn

C:车东的博客---http://www.chedong.com

D:Google黑板报---http://googlechinablog.com

E:搜狗实验室---http://www.sogou.com/labs/

F:Search Engine Watch,这是全球最大的搜索引擎研究站---http://searchenginewatch.com

 

6:搜索引擎算法

A:深度优先算法,B:广度优先算法,C:IP段扫描算法

更多的请参考:http://hi.baidu.com/chenhaoxian/blog/item/26d7560f14b69f2f6059f394.html

 

7:网页分析过程

单词提取->标点符号去除->大小写转换->超高频词汇去除->中文分词->提取URL,EMAIL,真正意文的文本信息等

 

8:信息检索模型分类

A:布尔模型,B:向量模型,C:概率模型,D:混合模型等

 

9:搜索引擎通常要解决的基本问题

A:信息抓取,B:数据解析,C:索引创建,D:执行检索

 

10:你要知道什么叫“倒排索引”

以字或词做为索引,非常适合“关键词”搜索

 

11:当前主流的索引技术

A:倒排索引

B:反缀数组

C:签名文件

------------------------------------------------------------------------------------------------------------

Lucene常识总结

12:Lucene中的分词方法

(1)单词切分

A:对于English和Chinese,我们用StandardAnalyzer就可以了

B:ChineseAnalyzer

(2)二分法

对于中文,可用CJKAnalyzer,NGram(综合了单词切分和二分法)

注:StandardAnalyzer,ChineseAnalyzer,CJKAnalyzer,NGram相关的jar包在:

%LUCENE%/contrib/analyzers/lucene-analyzer-2.1.0.jar包中,视版本不同而异

(3)词典法

如IK分词器,实现了正反向全切分算法,它包括了两个分析器,MIK_CAnalyzer使用最大全切分算法和IKAnalyzer使用细粒度全切分算法,相关jar包为:IKAnalyzer.jar

(4)语义法

(5)基于词库,如JE分词器,可以向词库中添加新词,查看词,删除词,相关jar包为:je-analysis-1.5.1.jar

Plus:中科院有个分词器,是dll形式,在Java中必须借助JNI,这样效率和效果都不好,容易死机,不建议采用

(6)好了,说了这么多分词器,最后推荐大家用JE分词器,足够了

 

13:常用二进制文档解析组件

A:PDF---PDFBox,从http://sourceforge.net/projects/pdfbox/下载PDFBox类库并解压,将external和lib下的jar包全copy到你的应用程序/lib下

B:WORD---用POI的一个组件包,textmining,从http://mirrors.ibiblio.org/pub/mirrors/maven2/org/textmining/tm-extractors/0.4/下载tm-extractors-0.4.zip

C:EXCEL---JExcel,从http://www.andykhan.com/jexcelapi/下载

D:XML---DOM4J,从http://www.dom4j.org/下载

E:HTML---HTMLParser,从http://htmlparser.sourceforge.net/下载,我们需要filterbuilder.jar,htmlparser.jar,htmllexer.jar,thumbelina.jar

F:Lius,用于从各种文档中提取文本信息,只是对PPT文档,只能解析出英文

注:推荐使用Lius,

 

14:索引创建方式

静态索引,动态索引(增量索引)

IndexWriter indexWriter = new IndexWriter(indexPath, new SimpleAnalyzer(), false);

第三个参数的意思就是:是否覆盖原来的索引,false时为增量索引

 

15:索引结构:

多文件索引,复合索引

调用indexWriter.useCompoundFile(false),为多文件索引,默认true为附和索引

多文件索引时,会创建很多的文件,在打索引开时,会占用大量的文件句柄资源,造成系统响应慢。而复合索引则会成n倍的减少文件数量,但是,统一文件存储大量数据会造成数据更新比较慢

 

16:建议不用IndexModifier,它在close时并没有真正删除Document,最好自己封装IndexWriter和IndexReader

 

17:不要过度使用“过滤器”,会有不小的性能开销

 

18:Lucene的逻辑组成,个人理解

lucene索引由多个“索引块”(segment)组成,增量索引以新块形式出现,每个“索引块”由多个“文档”(document)组成,每个“文档”由多个“索引域”(field)组成,“分析器”对每个“索引域”进行分析,拆分成很多“索引项”,最终构成了lucene的索引

 

19:Lucene的物理组成,个人理解

A:通常所说的索引指的是:在某个目录下的所有索引文件

B:多文件索引在创建时,至少会有fdt,fdx,fnm,frq,nrm,prx,tii,tis(这8个可以称为一个索引段)和segments.gen,segments_*10(这两个为独一的)文件,可以有单段多文件索引,也可以有多段多文件索引

C:复合索引在创建时,会将以上8个文件合并,形成一个cfs文件,再加个两个独一的文件,所以,它也有单段复合索引和多段复合索引两种

D:此外,多文件索引和复合索引还可以共存,但只有两个独一文件

E:最后我们通过IndexWriter.optimize(),对所有的文件进行优化成3个文件,cfs,segments.gen和segments_*

 

------------------------------------------------------------------------------------------------------------

实用分类总结

20:我们大至可以分为:

A:索引的建立和优化

B:索引的管理

C:解析用户请求

D:组合多条件搜索

E:过滤结果,进行排序,高亮处理等

 

21:索引建立和优化

一:建立

(1)增量索引:IndexWriter indexWriter = new IndexWriter(indexPath, new SimpleAnalyzer(), false);

(2)复合索引:indexWriter.useCompoundFile(true)

(3)Field参数含义,Field field = new Field(名称,内容,存储方式,索引方式);

存储方式有三种:Field.Store.NO(不存储),Field.Store.YES(存储),Field.Store.Compress(压缩存储)

索引方式有四种:Field.Index.NO(不索引),Field.Index.TOKENIZED(分词并索引),Field.Index.UN_TOKENIZED(不分词索引),Field.Index.NO_NORMS(禁用分析器处理)

(4)对不同文档Document使用不同分析器indexWriter.addDocument(doc,new StandardAnalyzer());

(5)限制Field词条数量,indexWriter.setMaxFieldLength(200);

(6)由于lucene采用统一的文档形式,所以对于非格式文本我们需要提前格式化,如数字和时间,最好定长表示,不足的用0补充,以保证检索和排序的正确性

二:优化

(1)利用缓存,减少磁盘读写频率

A:indexWriter.setMergeFactor(10),每10个document合并为一个索引块,每10个索引块合并成一个大索引块,每10个大索引块合并成更大的索引块,依次类推

B:indexWriter.setMaxBufferedDocs(100),用更多的内存换取更快的索引

C:先建立内存索引,再写入磁盘,用RAMDirectory

D:用indexWriter.optimize()自身优化

(2)减少索引文件数量和大小

 

22:索引的管理

A:了解索引本身信息,我们需要了解HITS,HIT,Document各自的属性和方法,请参照相应的API

B:索引的删除,添加,更新(本质是先删除,后添加)

创建表态索引用和增量索引用:IndexWriter

删除和添加索引用:IndexReader

用IndexReader删除某个Document,只是做了删除标记,不参与检索,要用IndexWriter.optimize()将其物理删除

C:不同目录的索引合并,用indexWriter.addIndexes(Directory directory),先把其中一个索引读入内存后优化,再用此方法加入到另一FSDirectory参数的indexWriter中,优化并关闭,这样这实现了两个索引的合并

D:推荐用Luke,是一套lucene索引管理的软件

 

23:解析用户请求

A:自己写程序分析,提取用户输入的关键字

B:用lucene自己的QueryParser解析,默认是OR逻辑

 

24:组合多条件搜索

A:用BooleanQuery可以实现“多索引域”搜索

B:MultiSearcher虽然可以多索引搜索,但实质还是一个一个顺序进行的,可以用ParallelMultiSearcher实现多线程多索引搜索

C:在BooleanQuery中,不能只含有BooleanClause.Occur.MUST_NOT,否则,只会返回空的结果集

D:组合用QueryParser,TermQuery,BooleanQuery,RegexQuery足以满足检索需求,如下:

Java代码 Lucene经验总结 - Simon - Simon

 

  1. String indexPath = "你的索引目录";   
  2. String word_list[] = {"中国","北京"};   
  3. String feild_list[] ={"feild_a","feild_b"};   
  4. IndexSearcher indexSearcher = new IndexSearcher(indexPath);   
  5. Analyzer analyzer = new StandardAnalyzer();   
  6. BooleanQuery boolQuery = new BooleanQuery();   
  7.   
  8. for(int i = 0;i < 2;i++){   
  9.     QueryParser parser = new QueryParser(feild_list[i],analyzer);   
  10.     Query query = parser.parse(word_list[i]);   
  11.     boolQuery.add(query,BooleanClause.Occur.SHOULD);   
  12. }   
  13. //以上实现了对用户输入的数据实现了lucene自带的QueryParser解析   
  14. //同时在相应的feild_a和feild_b索引域附进行检索   
  15.   
  16. Term ta = new Term("date","20090101");   
  17. Term tb = new Term("date","20090131");   
  18. RangeQuery rangeQuery = new RangeQuery(ta,tb,true);   
  19. //日期以年月日方式,定才存储,这样才可以得到正确结果,true表示包括边界   
  20.   
  21. boolQuery.add(rangeQuery,BooleanClause.Occur.MUST);   
  22.   
  23. Hits hits = indexSearcher.search(boolQuery);  

 

String indexPath = "你的索引目录";String word_list[] = {"中国","北京"};String feild_list[] ={"feild_a","feild_b"};IndexSearcher indexSearcher = new IndexSearcher(indexPath);Analyzer analyzer = new StandardAnalyzer();BooleanQuery boolQuery = new BooleanQuery();for(int i = 0;i < 2;i++){ QueryParser parser = new QueryParser(feild_list[i],analyzer); Query query = parser.parse(word_list[i]); boolQuery.add(query,BooleanClause.Occur.SHOULD);}//以上实现了对用户输入的数据实现了lucene自带的QueryParser解析//同时在相应的feild_a和feild_b索引域附进行检索Term ta = new Term("date","20090101");Term tb = new Term("date","20090131");RangeQuery rangeQuery = new RangeQuery(ta,tb,true);//日期以年月日方式,定才存储,这样才可以得到正确结果,true表示包括边界boolQuery.add(rangeQuery,BooleanClause.Occur.MUST);Hits hits = indexSearcher.search(boolQuery);

由此,我们可以实现,在用lucene自身QueryParser的前提下,

D-1:同一“索引域”中检索不同关键字

D-2:同一“索引域”中检索同一关键字

D-3:不同“索引域”中检索不同关键字

D-4:不同“索引域”中检索同一关键字

是不是够你一般的实际检索了!!

 

25:检索结果的过滤

A:QueryFilter带有缓存,其它的RangeFilter,PrefixFilter,ChainedFilter都不带有缓存,要用CachingWrapperFilter包装才可

B:尽量不用过滤器

C:两种过滤方式,一种是在搜索结果提取出来后过滤,另一种是把过滤条件加在搜索条件中,后者是其于前者的,由此可见,在搜索前加入太多搜索条件对性能有很大的影响,在有必要更精确的搜索时,还是建议使用前者吧

 

26:对检索结果进行排序

A:默认排序规则:得分-->时间

B:对多字段排序,如下

Java代码 Lucene经验总结 - Simon - Simon

 

  1. SortField sf1 = new SortField("id",false);//升序   
  2. SortField sf2 = new SortField("date",true);//降序   
  3. SortField fields[] = new SortField[]{sf1,sf2};   
  4. Sort sort = new Sort(fields);   
  5.   
  6. Hits hits = searcher.search(q,sort);//q是一个TermQuery  

 

SortField sf1 = new SortField("id",false);//升序SortField sf2 = new SortField("date",true);//降序SortField fields[] = new SortField[]{sf1,sf2};Sort sort = new Sort(fields);Hits hits = searcher.search(q,sort);//q是一个TermQuery

 

27:关于高亮显示

可以参照API和下面这个网址:

http://hi.baidu.com/deepeye/blog/item/83a8e8c4bec788ae8326ac5f.html

另外,我们也可以用Jquery,这个javascript框架来实现高亮显示,可以参考下面这个网址

效果一:http://www.cnblogs.com/yjmyzz/archive/2008/10/19/1314494.html

效果二:http://www.webwoo.org/jquery/200811/21-28450.html

 

28:其它搜索引擎参考:

1:sphinx

http://www.sphinxsearch.org/

http://dev.cgfinal.com/sphinx/sphinx.html

 

2:mysql全文检索

http://hi.baidu.com/longchengjiang/blog/item/ef9b05d32527f1083af3cf19.html

http://database.51cto.com/art/200902/111597.htm

以上是关于[转]Lucene经验总结 (转注:较旧,但有干货)的主要内容,如果未能解决你的问题,请参考以下文章

[转]Lucene学习总结之一:全文检索的基本原理

Lucene底层原理和优化经验分享-Lucene简介和索引原理

[转]MVC 经验总结_序

Android 开发60条技术经验总结(转)

SQL 优化经验总结34条(转)

转HADOOP HDFS BALANCER介绍及经验总结