阿翔编程学-Lucene入门与使用

Lucene入门与使用

       本文主要面向具体使用,适用于已熟悉java编程的lucene初学者。
1. Lucene
的简介

1.1 Lucene 历史

      org.apache.lucene包是纯java语言的全文索引检索工具包。
      Lucene
的作者是资深的全文索引/检索专家,最开始发布在他本人的主页上,200110月贡献给APACHE,成为APACHE基金jakarta的一个子项目。
     
目前,lucene广泛用于全文索引/检索的项目中。
      lucene
也被翻译成C#版本,目前发展为Lucene.Net(不过最近好象有流产的消息)。

1.2 Lucene 原理

       lucene的检索算法属于索引检索,即用空间来换取时间,对需要检索的文件、字符流进行全文索引,在检索的时候对索引进行快速的检索,得到检索位置,这个位置记录检索词出现的文件路径或者某个关键词。
      
在使用数据库的项目中,不使用数据库进行检索的原因主要是:数据库在非精确查询的时候使用查询语言“like %keyword%”,对数据库进行查询是对所有记录遍历,并对字段进行“%keyword%”匹配,在数据库的数据庞大以及某个字段存储的数据量庞大的时候,这种遍历是致命的,它需要对所有的记录进行匹配查询。因此,lucene主要适用于文档集的全文检索,以及海量数据库的模糊检索,特别是对数据库的xml或者大数据的字符类型。

2Lucene的下载和配置

2.1 Lucene的下载

       lucenejakarta项目中的发布主页:http://jakarta.apache.org/lucene/docs/index.html。以下主要针对windows用户,其它用户请在上面的地址中查找相关下载。

       lucene.jar包的下载(包括.jar和一个范例demo):
http://apache.oregonstate.edu/jakarta/lucene/binaries/lucene-1.4-final.zip

        lucene的源代码下载:
http://www.signal42.com/mirrors/apache/jakarta/lucene/source/lucene-1.4-final-src.zip

 luceneapi地址:http://jakarta.apache.org/lucene/docs/api/index.html

 本文使用lucene版本:lucene-1.4-final.jar

2.2 lucene的配置

        首先请确定你的机子已经进行了java使用环境的基本配置,即确保在某个平台下能够运行java源代码,否则请查阅相关文档进行配置。
       
接下来进入lucene的配置:
       
普通使用者:在环境变量的CLASSPATH中添加lucene的位置。比如:“D:/java /lucene-1.4-final/lucene-1.4-final.jar;”。
       jbuilder
使用者:在“Project--Project Properties--Required Libraries”进行添加。
       Jsp
使用者:也可以直接将lucene-1.4-final.jar文件放到/WEB-INF/classes下。

3. Lucene 的范例(Demo

3.1 Demo说明

     
       
可以得到的Demo包括:lucene-demos-1.4-finalXMLIndexingDemolucene-demos-1.4-final中包括对普通文件和html文件的两种索引,XMLIndexingDemo针对xml文件的索引。他们的区别主要在于:对普通文件进行索引时只要对文件的全文进行索引,而针对htmlxml文件时,对标签类型不能进行索引,在实现上:htmlxml的索引需要额外的数据流分析器,以分析哪些内容有用哪些无用。因此,在后两者实现上,索引的时间额外开支,甚至超过索引本身时间,而检索时间没有区别。

        以上Demo中,lucene-demos-1.4-final自带于lucene-1.4-final.zip中,XMLIndexingDemo的下载地址:
http://cvs.apache.org/viewcvs.cgi/jakarta-lucene-sandbox/contributions/XML-Indexing-Demo/

3.2 Demo的运行

        首先将demo.jar的路径添加如环境变量的CLASSPATH中,例如:“D:/java/lucene-1.4-final/lucene-demos-1.4-final.jar;”,同时确保已经添加lucene-1.4-final.jar

        然后进行文件的全文索引,在dos控制台中,输入命令“java org.apache.lucene.demo.IndexFiles {full-path-to-lucene}/src”,后面的路径为所要进行索引的文件夹,例如:“java org.apache.lucene.demo.IndexFiles c:/test”。

 

        接着对索引进行检索,敲入“java org.apache.lucene.demo.SearchFiles”,在提示“Query:”后输入检索词,程序将进行检索列出检索得到的结果(检索词出现的文件路径)。

       其他Demo的运行请参考/docs/demo.html
      
在运行Demo后请阅读Demo的源代码以便深入学习。

4. 利用Lucene进行索引

        进行lucene的熟悉后,我们将学习如何使用Lucene
 
一段索引的应用实例:

    //需要捕捉IOException异常
    //
建立一个IndexWriter,索引保存目录为“index
    String[] stopStrs = {
        "
他奶奶的", "***"};
    StandardAnalyzer analyzer = new StandardAnalyzer(stopStrs);
    IndexWriter writer = new IndexWriter("index", analyzer, true);
   
    //
添加一条文档
    Document doc = new Document();
    doc.add(Field.UnIndexed("id", "1"));//
id”为字段名,“ 1” 为字段值
    doc.add(Field.Text("text", "***
,他奶奶的,入门与使用"));
    writer.addDocument(doc);
   
    //
索引完成后的处理
    writer.optimize();
    writer.close();

       看完这段实例后,我们开始熟悉lucene的使用:

4.1 Lucene的索引接口

 在学习索引的时候,首先需要熟悉几个接口:

4.1.1 分析器Analyzer

        分析器主要工作是筛选,一段文档进来以后,经过它,出去的时候只剩下那些有用的部分,其他则剔除。而这个分析器也可以自己根据需要而编写。
        org.apache.lucene.analysis.Analyzer
:这是一个虚构类,以下两个借口均继承它而来。

        org.apache.lucene.analysis.SimpleAnalyzer:分析器,支持最简单拉丁语言。

        org.apache.lucene.analysis.standard.StandardAnalyzer:标准分析器,除了拉丁语言还支持亚洲语言,并在一些匹配功能上进行完善。在这个接口中还有一个很重要的构造函数:StandardAnalyzer(String[] stopWords),可以对分析器定义一些使用词语,这不仅可以免除检索一些无用信息,而且还可以在检索中定义禁止的政治性、非法性的检索关键词。

4.1.2 IndexWriter


        IndexWriter
的构造函数有三种接口,针对目录Directory、文件File、文件路径String三种情况。
例如IndexWriter(String path, Analyzer a, boolean create)path为文件路径,a为分析器,create标志是否重建索引(true:建立或者覆盖已存在的索引,false:扩展已存在的索引。)
      
一些重要的方法:

接口名

备注

addDocument(Document doc)

索引添加一个文档

addIndexes(Directory[] dirs)

将目录中已存在索引添加到这个索引

addIndexes(IndexReader[] readers)

将提供的索引添加到这个索引

optimize()

合并索引并优化

close()

关闭


       IndexWriter
为了减少大量的io维护操作,在每得到一定量的索引后建立新的小索引文件(笔者测试索引批量的最小单位为10),然后再定期将它们整合到一个索引文件中,因此在索引结束时必须进行wirter. optimize(),以便将所有索引合并优化。

4.1.3 org.apache.lucene.document

 以下介绍两种主要的类:
 a
org.apache.lucene.document.Document
        Document
文档类似数据库中的一条记录,可以由好几个字段(Field)组成,并且字段可以套用不同的类型(详细见b)。Document的几种接口:
 

接口名

备注

add(Field field)

添加一个字段(Field)到Document

String get(String name)

从文档中获得一个字段对应的文本

Field getField(String name)

由字段名获得字段值

Field[] getFields(String name)

由字段名获得字段值的集


 b
org.apache.lucene.document.Field
       
即上文所说的“字段”,它是Document的片段section
        Field
的构造函数:
       Field(String name, String string, boolean store, boolean index, boolean token)

        Indexed
:如果字段是Indexed的,表示这个字段是可检索的。
        Stored
:如果字段是Stored的,表示这个字段的值可以从检索结果中得到。
        Tokenized
:如果一个字段是Tokenized的,表示它是有经过Analyzer转变后成为一个tokens序列,在这个转变过程tokenization中,Analyzer提取出需要进行索引的文本,而剔除一些冗余的词句(例如:athe,they等,详见org.apache.lucene.analysis.StopAnalyzer.ENGLISH_STOP_WORDSorg.apache.lucene.analysis.standard.StandardAnalyzer(String[] stopWords)API)。Token是索引时候的基本单元,代表一个被索引的词,例如一个英文单词,或者一个汉字。因此,所有包含中文的文本都必须是Tokenized的。
     Field
的几种接口:

Name

Stored

Indexed

Tokenized

use

Keyword(String name,

        String value)

Y

Y

N

date,url

Text(String name, Reader value)

N

Y

Y

short text fields:

title,subject

Text(String name, String value)

Y

Y

Y

longer text fields,

like “body”

UnIndexed(String name,

String value)

Y

N

N

 

UnStored(String name,

         String value)

N

Y

Y

 

?

5. 利用Lucene进行检索

5.1 一段简单的检索代码

     //需要捕捉IOExceptionParseException异常
    //
处理检索条件
    Query query = QueryParser.parse("
入门", "text", analyzer);

    //检索
    Searcher searcher = new IndexSearcher("./index");//"index"
指定索引文件位置
Hits hits = searcher.search(query);

    //打印结果值集
    for (int i = 0; i < hits.length(); i++) {
      doc = hits.doc(i);
      String id = doc.get("id");
      System.out.println("found " + "
入门" + " on the id:" + id);
}

 5.2 利用Lucene的检索接口

5.2.1 QueryQueryParser


       
主要使用方法:
QueryParser .parse(String query, String field, Analyzer analyzer)
,例如:
Query query = QueryParser.parse("
入门", "text", analyzer);
"
入门"为检索词, "text"为检索的字段名, analyzer为分析器

5.2.2 HitsSearcher

       Hits的主要使用接口:
 

接口名

备注

Doc(int n)

返回第n个的文档的所有字段

length()

返回这个集中的可用个数

 

6. Lucene的其他使用

6.1 Lucene 的索引修改

        下面给出一段修改索引的代码,请根据LuceneAPI解读:


  /**
   *
对已有的索引添加新的一条索引
   * @param idStr String
:要修改的id
   * @param doc Document
:要修改的值
   */
  public void addIndex(String idStr, String valueStr) {
    StandardAnalyzer analyzer = new StandardAnalyzer();
    IndexWriter writer = null;
    try {
      writer = new IndexWriter(indexPath, analyzer, false);
      writer.mergeFactor = 2; //
修正lucene 1.4.2 bug,否则不能准确反映修改

          Document doc = new Document();
          doc.add(Field.UnIndexed("id", idStr));//
id”为字段名,“ 1” 为字段值
          doc.add(Field.Text("text", valueStr));
      writer.addDocument(doc);

      writer.optimize();
      writer.close();
    }
    catch (IOException ioe) {
      ioe.printStackTrace();
    }
  }

  /**
   *
删除索引
   *
   * @param idStr String
   */
  public void deleteIndex(String idStr) {
    try {
      Directory dirt = FSDirectory.getDirectory(indexPath, false);
      IndexReader reader = IndexReader.open(dirt);
      IndexXML.deleteIndex(idStr, reader);
      reader.close();
      dirt.close();
    }
    catch (IOException ioe) {
      ioe.printStackTrace();
    }
  }

6.2 Lucene 的检索结果排序

        Lucene的排序主要是对org.apache.lucene.search.Sort的使用。Sort可以直接根据字段Field生成,也可以根据标准的SortField生成,但是作为Sort的字段,必须符合以下的条件:唯一值以及Indexed。可以对Integers, Floats, Strings三种类型排序。
       
对整数型的ID检索结果排序只要进行以下的简单操作:

 Sort sort = new Sort("id");
Hits hits = searcher.search(query, sort);

       用户还可以根据自己定义更加复杂的排序,详细请参考API

7 总结

        Lucenejava的全文索引检索带来了非常强大的力量,以上仅对Lucene进行简单的入门说明。

参考资料:
1. Overview (Lucene 1.4-final API)
2.
车东 《在应用中加入全文检索功能--基于JAVA的全文索引引擎Lucene简介》
3. http://www.mail-archive.com/lucene-user@jakarta.apache.org/index.html

 

 Lucene原理

Lucene是一个高性能的java全文检索工具包,它使用的是倒排文件索引结构。该结构及相应的生成算法如下:

0
)设有两篇文章12
文章1的内容为:Tom lives in Guangzhou ,I live in Guangzhou too.
文章2的内容为:He once lived in Shanghai .

1)
由于lucene是基于关键词索引和查询的,首先我们要取得这两篇文章的关键词,通常我们需要如下处理措施
a.
我们现在有的是文章内容,即一个字符串,我们先要找出字符串中的所有单词,即分词。英文单词由于用空格分隔,比较好处理。中文单词间是连在一起的需要特殊的分词处理。
b.
文章中的”in”, “once” “too”等词没有什么实际意义,中文中的”“等字通常也无具体含义,这些不代表概念的词可以过滤掉
c.
用户通常希望查“He”时能把含“he”“HE”的文章也找出来,所以所有单词需要统一大小写。
d.
用户通常希望查“live”时能把含“lives”“lived”的文章也找出来,所以需要把“lives”“lived”还原成“live”
e.
文章中的标点符号通常不表示某种概念,也可以过滤掉
lucene中以上措施由Analyzer类完成

经过上面处理后
文章1的所有关键词为:[tom] [live] [guangzhou] [i] [live] [guangzhou]
文章2的所有关键词为:[he] [live] [shanghai]

2)
有了关键词后,我们就可以建立倒排索引了。上面的对应关系是:文章号文章中所有关键词。倒排索引把这个关系倒过来,变成:关键词拥有该关键词的所有文章号。文章12经过倒排后变成
关键词 文章号
guangzhou 1
he 2
i 1
live 1,2
shanghai 2
tom 1

通常仅知道关键词在哪些文章中出现还不够,我们还需要知道关键词在文章中出现次数和出现的位置,通常有两种位置:a)字符位置,即记录该词是文章中第几个字符(优点是关键词亮显时定位快);b)关键词位置,即记录该词是文章中第几个关键词(优点是节约索引空间、词组(phase)查询快),lucene中记录的就是这种位置。

加上出现频率出现位置信息后,我们的索引结构变为:
关键词 文章号[出现频率] 出现位置
guangzhou 1[2] 3
6
he 2[1] 1
i 1[1] 4
live 1[2],2[1] 2
52
shanghai 2[1] 3
tom 1[1] 1

live 这行为例我们说明一下该结构:live在文章1中出现了2次,文章2中出现了一次,它的出现位置为“2,5, 2” 这表示什么呢?我们需要结合文章号和出现频率来分析,文章1中出现了2次,那么“2, 5” 就表示live在文章1中出现的两个位置,文章2中出现了一次,剩下的“ 2” 就表示live是文章2中第 2个关键字。

以上就是lucene索引结构中最核心的部分。我们注意到关键字是按字符顺序排列的(lucene没有使用B树结构),因此lucene可以用二元搜索算法快速定位关键词。

实现时 lucene将上面三列分别作为词典文件(Term Dictionary)、频率文件(frequencies)、位置文件 (positions)保存。其中词典文件不仅保存有每个关键词,还保留了指向频率文件和位置文件的指针,通过指针可以找到该关键字的频率信息和位置信息。

Lucene
中使用了field的概念,用于表达信息所在位置(如标题中,文章中,url中),在建索引中,该field信息也记录在词典文件中,每个关键词都有一个field信息(因为每个关键字一定属于一个或多个field)

为了减小索引文件的大小,Lucene对索引还使用了压缩技术。首先,对词典文件中的关键词进行了压缩,关键词压缩为<前缀长度,后缀>,例如:当前词为阿拉伯语,上一个词为阿拉伯,那么阿拉伯语压缩为<3,语>。其次大量用到的是对数字的压缩,数字只保存与上一个值的差值(这样可以减小数字的长度,进而减少保存该数字需要的字节数)。例如当前文章号是16389(不压缩要用3个字节保存),上一文章号是16382,压缩后保存7(只用一个字节)。

下面我们可以通过对该索引的查询来解释一下为什么要建立索引。
假设要查询单词 “live”lucene先对词典二元查找、找到该词,通过指向频率文件的指针读出所有文章号,然后返回结果。词典通常非常小,因而,整个过程的时间是毫秒级的。
而用普通的顺序匹配算法,不建索引,而是对所有文章的内容进行字符串匹配,这个过程将会相当缓慢,当文章数目很大时,时间往往是无法忍受的。

Lucene讲座

第一节 全文检索系统与Lucene简介··· 3

一、       什么是全文检索与全文检索系统?··· 3

二、       什么是Lucene··· 4

三、       Lucene的应用、特点及优势··· 4

四、       本文的重点问题与cLucene项目··· 5

第二节 Lucene系统结构分析··· 5

一、       系统结构组织··· 5

二、       数据流分析··· 6

三、       基于Lucene的应用开发··· 8

第三节 Lucene索引文件格式分析··· 9

一、       Lucene源码实现分析的说明··· 9

二、       Lucene索引文件格式··· 10

三、       一些公用的基础类··· 12

四、       存储抽象··· 13

五、       关于cLucene项目··· 15

第四节 Lucene索引构建逻辑模块分析··· 15

一、       绪论··· 15

二、       对象体系与UML··· 16

1     项(Term··· 16

2     域(Field··· 17

3     文档(document··· 18

4     段(segment··· 19

5     IndexReader类与IndexWirter··· 23

三、       数据流逻辑··· 24

四、       关于cLucene项目··· 25

 

 

第一节 全文检索系统与Lucene简介

 

一、             什么是全文检索与全文检索系统?

 

全文检索是指计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。这个过程类似于通过字典中的检索字表查字的过程。

 

全文检索的方法主要分为按字检索和按词检索两种。按字检索是指对于文章中的每一个字都建立索引,检索时将词分解为字的组合。对于各种不同的语言而言,字有不同的含义,比如英文中字与词实际上是合一的,而中文中字与词有很大分别。按词检索指对文章中的词,即语义单位建立索引,检索时按词检索,并且可以处理同义项等。英文等西方文字由于按照空白切分词,因此实现上与按字处理类似,添加同义处理也很容易。中文等东方文字则需要切分字词,以达到按词索引的目的,关于这方面的问题,是当前全文检索技术尤其是中文全文检索技术中的难点,在此不做详述。

 

全文检索系统是按照全文检索理论建立起来的用于提供全文检索服务的软件系统。一般来说,全文检索需要具备建立索引和提供查询的基本功能,此外现代的全文检索系统还需要具有方便的用户接口、面向WWW[1]的开发接口、二次应用开发接口等等。功能上,全文检索系统核心具有建立索引、处理查询返回结果集、增加索引、优化索引结构等等功能,外围则由各种不同应用具有的功能组成。结构上,全文检索系统核心具有索引引擎、查询引擎、文本分析引擎、对外接口等等,加上各种外围应用系统等等共同构成了全文检索系统。图1.1展示了上述全文检索系统的结构与功能。

 

在上图中,我们看到:全文检索系统中最为关键的部分是全文检索引擎,各种应用程序都需要建立在这个引擎之上。一个全文检索应用的优异程度,根本上由全文检索引擎来决定。因此提升全文检索引擎的效率即是我们提升全文检索应用的根本。另一个方面,一个优异的全文检索引擎,在做到效率优化的同时,还需要具有开放的体系结构,以方便程序员对整个系统进行优化改造,或者是添加原有系统没有的功能。比如在当今多语言处理的环境下,有时需要给全文检索系统添加处理某种语言或者文本格式的功能,比如在英文系统中添加中文处理功能,在纯文本系统中添加XML[2]或者HTML[3]格式的文本处理功能,系统的开放性和扩充性就十分的重要。

 

二、             什么是Lucene

 

Luceneapache软件基金会[4] jakarta项目组的一个子项目,是一个开放源代码[5]的全文检索引擎工具包,即它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言)。Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。

 

Lucene的原作者是Doug Cutting,他是一位资深全文索引/检索专家,曾经是V-Twin搜索引擎[6]的主要开发者,后在Excite[7]担任高级系统架构设计师,目前从事于一些Internet底层架构的研究。早先发布在作者自己的http://www.lucene.com/,后来发布在SourceForge[8]2001年年底成为apache软件基金会jakarta的一个子项目:http://jakarta.apache.org/lucene/

 

三、             Lucene的应用、特点及优势

 

作为一个开放源代码项目,Lucene从问世之后,引发了开放源代码社群的巨大反响,程序员们不仅使用它构建具体的全文检索应用,而且将之集成到各种系统软件中去,以及构建Web应用,甚至某些商业软件也采用了Lucene作为其内部全文检索子系统的核心。apache软件基金会的网站使用了Lucene作为全文检索的引擎,IBM的开源软件eclipse[9]2.1版本中也采用了Lucene作为帮助子系统的全文索引引擎,相应的IBM的商业软件Web Sphere[10]中也采用了LuceneLucene以其开放源代码的特性、优异的索引结构、良好的系统架构获得了越来越多的应用。

 

Lucene作为一个全文检索引擎,其具有如下突出的优点:

1)索引文件格式独立于应用平台。Lucene定义了一套以8位字节为基础的索引文件格式,使得兼容系统或者不同平台的应用能够共享建立的索引文件。

2)在传统全文检索引擎的倒排索引的基础上,实现了分块索引,能够针对新的文件建立小文件索引,提升索引速度。然后通过与原有索引的合并,达到优化的目的。

3)优秀的面向对象的系统架构,使得对于Lucene扩展的学习难度降低,方便扩充新功能。

4)设计了独立于语言和文件格式的文本分析接口,索引器通过接受Token流完成索引文件的创立,用户扩展新的语言和文件格式,只需要实现文本分析的接口。

5)已经默认实现了一套强大的查询引擎,用户无需自己编写代码即使系统可获得强大的查询能力,Lucene的查询实现中默认实现了布尔操作、模糊查询(Fuzzy Search[11])、分组查询等等。

 

    面对已经存在的商业全文检索引擎,Lucene也具有相当的优势。首先,它的开发源代码发行方式(遵守Apache Software License[12]),在此基础上程序员不仅仅可以充分的利用Lucene所提供的强大功能,而且可以深入细致的学习到全文检索引擎制作技术和面相对象编程的实践,进而在此基础上根据应用的实际情况编写出更好的更适合当前应用的全文检索引擎。在这一点上,商业软件的灵活性远远不及Lucene。其次,Lucene秉承了开放源代码一贯的架构优良的优势,设计了一个合理而极具扩充能力的面向对象架构,程序员可以在Lucene的基础上扩充各种功能,比如扩充中文处理能力,从文本扩充到HTMLPDF[13]等等文本格式的处理,编写这些扩展的功能不仅仅不复杂,而且由于Lucene恰当合理的对系统设备做了程序上的抽象,扩展的功能也能轻易的达到跨平台的能力。最后,转移到apache软件基金会后,借助于apache软件基金会的网络平台,程序员可以方便的和开发者、其它程序员交流,促成资源的共享,甚至直接获得已经编写完备的扩充功能。最后,虽然Lucene使用Java语言写成,但是开放源代码社区的程序员正在不懈的将之使用各种传统语言实现(例如.net framework[14]),在遵守Lucene索引文件格式的基础上,使得Lucene能够运行在各种各样的平台上,系统管理员可以根据当前的平台适合的语言来合理的选择。

 

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值