个机制的结合。关于中文的语言分析算法,大家可以在Google查关键词"wordsegment search"能找到更多相关的资料。

安装和使用

下载:http://jakarta.apache.org/lucene/

注意:Lucene中的一些比较复杂的词法分析是用JavaCC生成的(JavaCC:JavaCompilerCompiler,纯Java的词法分析生成器),所以如果从源代码编译或需要修改其中的QueryParser、定制自己的词法分析器,还需要从https://javacc.dev.java.net/下载javacc。

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(String name, String value)

Yes

Yes

Yes

切分词索引并存储,比如:标题,内容字段

Field.Text(String name, Reader value)

Yes

Yes

No

切分词索引不存储,比如:META信息,
不用于返回显示,但需要进行检索内容

Field.Keyword(String name, String value)

No

Yes

Yes

不切分索引并存储,比如:日期字段

Field.UnIndexed(String name, String value)

No

No

Yes

不索引,只存储,比如:文件路径

Field.UnStored(String name, String value)

Yes

Yes

No

只全文索引,不存储

public classIndexFiles {
  //使用方法:: IndexFiles [索引输出目录] [索引的文件列表] ...
  public static void main(String[] args)throws Exception {
    String indexPath = args[0];
    IndexWriter writer;
    //用指定的语言分析器构造一个新的写索引器(第3个参数表示是否为追加索引)
    writer = new IndexWriter(indexPath,new SimpleAnalyzer(), false);

    for (int i=1; i<args.length; i++){
      System.out.println("Indexingfile " + args[i]);
      InputStream is = new FileInputStream(args[i]);

      //构造包含2个字段Field的Document对象
      //一个是路径path字段,不索引,只存储
      //一个是内容body字段,进行全文索引,并存储
      Document doc = new Document();
     doc.add(Field.UnIndexed("path", args[i]));
     doc.add(Field.Text("body", (Reader) new InputStreamReader(is)));
      //将文档写入索引
      writer.addDocument(doc);
      is.close();
    };
    //关闭写索引器
    writer.close();
  }
}

个分析器。

· Lucene并没有规定数据源的格式,而只提供了一个通用的结构(Document对象)来接受索引的输入,因此输入的数据源可以是:数据库,WORD文档,PDF文档,HTML文档……只要能够设计相应的解析转换器将数据源构造成成Docuement对象即可进行索引。

· 对于大批量的数据索引,还可以通过调整IndexerWrite的文件合并频率属性(mergeFactor)来提高批量索引的效率。

检索过程和结果显示:

搜索结果返回的是Hits对象,可以通过它再访问Document==>Field中的内容。

假设根据body字段进行全文检索,可以将查询结果的path字段和相应查询的匹配度(score)打印出来,

public class Search{
  public static void main(String[] args)throws Exception {
    String indexPath = args[0],queryString = args[1];
    //指向索引目录的搜索器
    Searcher searcher = newIndexSearcher(indexPath);
    //查询解析器:使用和索引同样的语言分析器
    Query query =QueryParser.parse(queryString, "body",
                              newSimpleAnalyzer());
    //搜索结果使用Hits存储
    Hits hits = searcher.search(query);
    //通过hits可以访问到相应字段的数据和查询的匹配度
    for (int i=0; i<hits.length();i++) {
     System.out.println(hits.doc(i).get("path") + "; Score:" +
                         hits.score(i));
    };
  }
}

个参数,所以,基于score以外的排序,其实可以通过将数据源预先排好序,然后根据docID进行排序来实现。这样就避免了在LUCENE搜索结果外对结果再次进行排序和在搜索过程中访问不在索引中的某个字段值。

这里需要修改的是IndexSearcher中的HitCollector过程:

...

 scorer.score(newHitCollector() {
        private float minScore = 0.0f;
        public final void collect(int doc,float score) {
         if (score > 0.0f &&                   // ignore zeroed buckets
              (bits==null || bits.get(doc))) {         // skip docs not in bits
           totalHits[0]++;
           if (score >= minScore) {
              /* 原先:Lucene将docID和相应的匹配度score例入结果命中列表中:
               *hq.put(new ScoreDoc(doc, score));      // update hit queue
               * 如果用doc 或 1/doc 代替 score,就实现了根据docID顺排或逆排
               * 假设数据源索引时已经按照某个字段排好了序,而结果根据docID排序也就实现了
               * 针对某个字段的排序,甚至可以实现更复杂的score和docID的拟合。
               */
              hq.put(new ScoreDoc(doc, (float) 1/doc ));
              if (hq.size() > nDocs) {         // if hit queue overfull
               hq.pop();                        // remove lowest in hit queue
               minScore =((ScoreDoc)hq.top()).score; // reset minScore
              }
           }
         }
        }
      }, reader.maxDoc());

个版本,一个是通过JavaCC生成的,对CJK部分按一个字符一个TOKEN索引,另外一个是从SimpleTokenizer改写的,对英文支持数字和字母TOKEN,对中文按迭代索引。

·  基于XML数据源的索引器:XMLIndexer,因此所有数据源只要能够按照DTD转换成指定的XML,就可以用XMLIndxer进行索引了。

·  根据某个字段排序:按记录索引顺序排序结果的搜索器:IndexOrderSearcher,因此如果需要让搜索结果根据某个字段排序,可以让数据源先按某个字段排好序(比如:PriceField),这样索引后,然后在利用这个按记录的ID顺序检索的搜索器,结果就是相当于是那个字段排序的结果了。

从Lucene学到更多

Luene的确是一个面对对象设计的典范

·  所有的问题都通过一个额外抽象层来方便以后的扩展和重用:你可以通过重新实现来达到自己的目的,而对其他模块而不需要;

·  简单的应用入口Searcher, Indexer,并调用底层一系列组件协同的完成搜索任务;

·  所有的对象的任务都非常专一:比如搜索过程:QueryParser分析将查询语句转换成一系列的精确查询的组合(Query),通过底层的索引读取结构IndexReader进行索引的读取,并用相应的打分器给搜索结果进行打分/排序等。所有的功能模块原子化程度非常高,因此可以通过重新实现而不需要修改其他模块。

·  除了灵活的应用接口设计,Lucene还提供了一些适合大多数应用的语言分析器实现(SimpleAnalyser,StandardAnalyser),这也是新用户能够很快上手的重要原因之一。

这些优点都是非常值得在以后的开发中学习借鉴的。作为一个通用工具包,Lunece的确给予了需要将全文检索功能嵌入到应用中的开发者很多的便利。

此外,通过对Lucene的学习和使用,我也更深刻地理解了为什么很多数据库优化设计中要求,比如:

·  尽可能对字段进行索引来提高查询速度,但过多的索引会对数据库表的更新操作变慢,而对结果过多的排序条件,实际上往往也是性能的杀手之一。

·  很多商业数据库对大批量的数据插入操作会提供一些优化参数,这个作用和索引器的merge_factor的作用是类似的,

·  20%/80%原则:查的结果多并不等于质量好,尤其对于返回结果集很大,如何优化这头几十条结果的质量往往才是最重要的。

·  尽可能让应用从数据库中获得比较小的结果集,因为即使对于大型数据库,对结果集的随机访问也是一个非常消耗资源的操作。

Lucene 学习资料的更多相关文章

  1. Apache Lucene学习笔记

    Hadoop概述 Apache lucene: 全球第一个开源的全文检索引擎工具包 完整的查询引擎和搜索引擎 部分文本分析引擎 开发人员在此基础建立完整的全文检索引擎 以下为转载:http://www ...

  2. Lucene学习入门——下载初识

    本文从官网下载Lucene开始,一步一步进行Lucene的应用学习研究.下载初识Snowball Stemmer 1.下载 (1)首先,去Lucne的Apache官网主页 http://lucene. ...

  3. webapi的学习资料

    猿教程_-webapi教程-WebAPI教程 猿教程_-webapi教程-Web API概述 猿教程_-webapi教程-新建Web Api项目 猿教程_-webapi教程-测试Web API 猿教程 ...

  4. netty学习资料

    netty学习资料推荐官方文档和<netty权威指南>和<netty in action>这两本书.下面收集下网上分享的资料 netty官方参考文档 Netty 4.x Use ...

  5. iOS 开发学习资料整理(持续更新)

      “如果说我看得比别人远些,那是因为我站在巨人们的肩膀上.” ---牛顿   iOS及Mac开源项目和学习资料[超级全面] http://www.kancloud.cn/digest/ios-mac ...

  6. 最新JavaScript、Ajax典藏级学习资料下载分类汇总 (2011年12月21日更新)

    其他网站开发相关资料            超强HTML和xhtml,CSS精品学习资料下载汇总                                               最新htm ...

  7. VC++/MFC(VC6)开发技术精品学习资料下载汇总

    工欲善其事,必先利其器,VC开发MFC Windows程序,Visual C++或Visual Studio是必须的,恩,这里都给你总结好了,拿去吧:VC/MFC开发必备Visual C++.Visu ...

  8. C/C++编程语言学习资料尽收眼底 电子书+视频教程

    Visual C++(VC/MFC)学习电子书及开发工具下载请看这里 史无前例的网络最全最强C/C++资料索引: C/C++编程语言学习资料尽收眼底 电子书+视频教程 VC++/MFC(VC6)开发技 ...

  9. yaf学习资料

    yaf学习资料 文档 鸟哥的官方文档 Yaf框架结合PHPUnit的集成测试 php yaf框架扩展实践六--单元测试.计划任务.第三方库等 php yaf框架扩展实践一--配置篇 yaf实战例子 y ...

随机推荐

  1. 数组中的数分为两组,让给出一个算法,使得两个组的和的差的绝对值最小,数组中的数的取值范围是0<x<100,元素个数也是大于0, 小于100 。

    比如a[]={2,4,5,6,7},得出的两组数{2,4,6}和{5,7},abs(sum(a1)-sum(a2))=0: 比如{2,5,6,10},abs(sum(2,10)-sum(5,6))=1 ...

  2. win 8.1 64位彻底删除王码98

    安全模式 C:\Windows\SysWOW64\ 删除:winwb98.IME和winwb98.MB 注册表: 找到王码五笔相关的项.一般在最下面的以字母E开头的文件夹.全部删除. HKEY_LOC ...

  3. antlr 4新特性总结及与antlr v3的不同

    antlr 4新特性总结及与antlr v3的不同 学习曲线低.antlr v4相对于v3,v4更注重于用更接近于自然语言的方式去解析语言.比如运算符优先级,排在最前面的规则优先级最高: 层次更清晰. ...

  4. [线程]Thead 中传参数RuntimeError: thread.__init__() not called

    在写一个多线程类的时候调用报错 RuntimeError: thread.__init__() not called class NotifyTread(threading.Thread): def ...

  5. 关于React Native项目在android上UI性能调试实践

    我们尽最大的努力来争取使UI组件的性能如丝般顺滑,但有的时候这根本不可能做到.要知道,Android有超过一万种不同型号的手机,而在框架底层进行软件渲染的时候是统一处理的,这意味着你没办法像iOS那样 ...

  6. 剑指Offer——贪心算法

    剑指Offer--贪心算法 一.基本概念 所谓贪心算法是指,在对问题求解时,总是做出在当前看来是最好的选择.也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解.虽然贪心算法不能对 ...

  7. 怎样在Ubuntu 14.04中搭建gitolite git服务器

     1.   首先这里我们安装openssh-serveropenssh-client,如果你用的是VPS之类的一般都默认安装好了,不过运行一个这个命令不会有错的,如果有安装就会提示已安装. sud ...

  8. SSH深度历险(七) 剖析SSH核心原理(一)

    接触SSH有一段时间了,但是对于其原理,之前说不出来莫模模糊糊(不能使用自己的语言描述出来的就是没有掌握),在视频和GXPT学习,主要是实现了代码,一些原理性的内容还是欠缺的,这几天我自己也一直在反问 ...

  9. 步步为营---- MuleEsb学习(一) 扫盲篇

    本篇文章是基于不断的接触GXPT之后,对其技术开始不断的积累学习^^^,有很多问题带给我了思考,对于如何的处理各个部分的流程?这个如何处理?太多的问题促使着我一步一步的学习,在师哥们的指导下,逐步的清 ...

  10. UNIX网络编程——UDP 的connect函数(改进版)

    上一篇我们提到,除非套接字已连接,否则异步错误是不会返回到UDP套接字的.我们确实可以给UDP套接字调用connect,然而这样做的结果却与TCP连接大相径庭:没有三次握手.内核只是检查是否存在立即可 ...