zoukankan      html  css  js  c++  java
  • [转]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

  • 相关阅读:
    HTTP请求 GET POST 网络编程实现(转)
    较老版本 AFNetworking 使用心得
    优秀java开源项目与解决方案推荐与概论
    URL的格式scheme
    用MATLAB实现字符串分割
    matlab search path
    matlab中的字符串数组与函数调用
    全新重装win8.1系统后 配置开发及办公环境步骤
    html图片上下翻滚展示代码
    html目录树的操作
  • 原文地址:https://www.cnblogs.com/maizhongfei/p/5838651.html
Copyright © 2011-2022 走看看