`
liu_bia
  • 浏览: 109234 次
  • 性别: Icon_minigender_1
  • 来自: 西安
文章分类
社区版块
存档分类
最新评论
  • ztbzg: 学习了,今天用上了,多谢lz 以前动态增加div 是直接拼字符 ...
    动态生成层
阅读更多

本文主要介绍了Lucene的起源、发展、现状,以及Luence的初步应用,可以作为了解和学习Lucene的入门资料。

1.起源与发展

Lucene是一个高性能、纯Java的全文检索引擎,而且免费、开源。Lucene几乎适合于任何需要全文检索的应用,尤其是跨平台的应用。

Lucene的作者Doug Cutting是一个资深的全文检索专家,刚开始,Doug Cutting将Lucene发表在自己的主页上,2000年3月将其转移到sourceforge,于2001年10捐献给Apache,作为Jakarta的一个子工程。

2.使用现状

经过多年的发展,Lucene在全文检索领域已经有了很多的成功案例,并积累了良好的声誉。

基于Lucene的全文检索产品(Lucene本身只是一个组件,而非一个完整的应用)和应用Lucene的项目在世界各地已经非常之多,比较知名的有:

l         Eclipse:主流Java开发工具,其帮助文档采用Lucene作为检索引擎

l         Jive:知名论坛系统,其检索功能基于Lucene

l         Ifinder:出自德国的网站检索系统,基于Lucene(http://ifinder.intrafind.org/)

l         MIT DSpace Federation:一个文档管理系统(http://www.dspace.org/)

国内外采用Lucene作为网站全文检索引擎的也很多,比较知名的有:

l         http://www.blogchina.com/weblucene/

l         http://www.ioffer.com/

l         http://search.soufun.com/

l         http://www.taminn.com/

(更多案例,请参见http://wiki.apache.org/jakarta-lucene/PoweredBy

在所有这些案例中,开源应用占了很大一部分,但更多的还是商化业产品和网站。毫不夸张的说,Lucene的出现,极大的推动了全文检索技术在各个行业或领域中的深层次应用。

3.初步应用

前面提到,Lucene本身只是一个组件,而非一个完整的应用,所以若想让Lucene跑起来,还得在Lucene基础上进行必要的二次开发。

下载与安装

首先,你需要到Lucene的官方网站http://jakarta.apache.org/lucene/ 去下载一份拷贝,最新版是1.4。下载后将得到一个名为lucene-1.4-final.zip的压缩文件,将其解压,里面有一个名为lucene-1.4-final.jar的文件,这就是Lucene组件包了,若需要在项目使用Lucene,只需要把lucene-1.4-final.jar置于类路径下即可,至于解压后的其他文件都是参考用的。

接下来,我用Eclipse建立一个工程,实现基于Lucene的建库、记录加载和记录查询等功能。

 

如上图所示,这是开发完成后的工程,其中有三个源文件CreateDataBase.java,InsertRecords.java,QueryRecords.java,分别实现建库、入库、检索的功能。

以下是对这三个源文件的分析。

建库源码及说明

 

CreateDataBase.java

packagecom.holen.part1;

 

importjava.io.File;

importorg.apache.lucene.analysis.standard.StandardAnalyzer;

importorg.apache.lucene.index.IndexWriter;

 

/**

 * @authorHolenChen

 *初始化检索库

 */

public classCreateDataBase{

 

    publicCreateDataBase(){  

    }

   

    public intcreateDataBase(Filefile){

       intreturnValue=0;

       if(!file.isDirectory()){

           file.mkdirs();

       }

       try{

           IndexWriterindexWriter= newIndexWriter(file,newStandardAnalyzer(),true);

           indexWriter.close();

           returnValue=1;

       }catch(Exceptionex){

           ex.printStackTrace();

       }

       returnreturnValue;

    }

   

    /**

     *传入检索库路径,初始化库

     * @paramfile

     * @return

     */

    public intcreateDataBase(Stringfile){

       return this.createDataBase(newFile(file));  

    }

 

    public static voidmain(String[]args){

       CreateDataBasetemp= newCreateDataBase();

       if(temp.createDataBase("e:\\lucene\\holendb")==1){

           System.out.println("db init succ");

       }

    }

}

 

 

说明:这里最关键的语句是IndexWriterindexWriter= newIndexWriter(file,newStandardAnalyzer(),true)。

 

第一个参数是库的路径,也就是说你准备把全文检索库保存在哪个位置,比如main方法中设定的“e:\\lucene\\holendb”,Lucene支持多库,且每个库的位置允许不同。

第二个参数是分析器,这里采用的是Lucene自带的标准分析器,分析器用于对整篇文章进行分词解析,这里的标准分析器实现对英文(或拉丁文,凡是由字母组成,由空格分开的文字均可)的分词,分析器将把整篇英文按空格切成一个个的单词(在全文检索里这叫切词,切词是全文检索的核心技术之一,Lucene默认只能切英文或其他拉丁文,默认不支持中日韩等双字节文字,关于中文切词技术将在后续章节重点探讨)。

第三个参数是是否初始化库,这里我设的是true,true意味着新建库或覆盖已经存在的库,false意味着追加到已经存在的库。这里新建库,所以肯定需要初始化,初始化后,库目录下只存在一个名为segments的文件,大小为1k。但是当库中存在记录时执行初始化,库中内容将全部丢失,库回复到初始状态,即相当于新建了该库,所以真正做项目时,该方法一定要慎用。

加载记录源码及说明

 

InsertRecords.java

packagecom.holen.part1;

 

importjava.io.File;

importjava.io.FileReader;

importjava.io.Reader;

importorg.apache.lucene.analysis.standard.StandardAnalyzer;

importorg.apache.lucene.document.Document;

importorg.apache.lucene.document.Field;

importorg.apache.lucene.index.IndexWriter;

 

/**

 * @authorHolenChen

 *记录加载

 */

public classInsertRecords{

 

    publicInsertRecords(){

    }

   

    public intinsertRecords(Stringdbpath,Filefile){

       intreturnValue=0;

       try{

           IndexWriterindexWriter

            = newIndexWriter(dbpath,newStandardAnalyzer(),false);

           this.addFiles(indexWriter,file);

           returnValue=1;

       }catch(Exceptionex){

           ex.printStackTrace();

       }

       returnreturnValue;

    }

   

    /**

     *传入需加载的文件名

     * @paramfile

     * @return

     */

    public intinsertRecords(Stringdbpath,Stringfile){

       return this.insertRecords(dbpath,newFile(file));

    }

   

    public voidaddFiles(IndexWriterindexWriter,Filefile){

       Documentdoc= newDocument();

       try{

           doc.add(Field.Keyword("filename",file.getName()));  

                 

           //以下两句只能取一句,前者是索引不存储,后者是索引且存储

           //doc.add(Field.Text("content",new FileReader(file))); 

           doc.add(Field.Text("content",this.chgFileToString(file)));

          

           indexWriter.addDocument(doc);

           indexWriter.close();

       }catch(Exceptionex){

           ex.printStackTrace();

       }

    }

   

    /**

     *从文本文件中读取内容

     * @paramfile

     * @return

     */

    publicStringchgFileToString(Filefile){

       StringreturnValue= null;

       StringBuffersb= newStringBuffer();

       char[]c= new char[4096];

       try{

           Readerreader= newFileReader(file);

           intn=0;

           while(true){            

              n=reader.read(c);

              if(n>0){

                  sb.append(c,0,n);

              }else{

                  break;

              }

           }

           reader.close();

       }catch(Exceptionex){

           ex.printStackTrace();

       }

       returnValue=sb.toString();

       returnreturnValue; 

    }

 

    public static voidmain(String[]args){

       InsertRecordstemp= newInsertRecords();

       Stringdbpath="e:\\lucene\\holendb";

       //holen1.txt中包含关键字"holen"和"java"

       if(temp.insertRecords(dbpath,"e:\\lucene\\holen1.txt")==1){

           System.out.println("add file1 succ");

       }

       //holen2.txt中包含关键字"holen"和"chen"

       if(temp.insertRecords(dbpath,"e:\\lucene\\holen2.txt")==1){

           System.out.println("add file2 succ");

       }  

    }

}

 


说明:这个类里面主要有3个方法insertRecords(Stringdbpath,Filefile),addFiles(IndexWriterindexWriter,Filefile),chgFileToString(Filefile)。

 

ChgFileToString方法用于读取文本型文件到一个String变量中。

 

InsertRecords方法用于加载一条记录,这里是将单个文件入全文检索库,第一个参数是库路径,第二个参数是需要入库的文件。

 

InsertRecords需要调用addFiles,addFiles是文件入库的真正执行者。AddFiles里有如下几行重点代码:

doc.add(Field.Keyword("filename",file.getName()));

注意,在Lucene里没有严格意义上表,Lucene的表是通过Field类的方法动态构建的,比如Field.Keyword("filename",file.getName())就相当于在一条记录加了一个字段,字段名为filename,该字段的内容为file.getName()。

 

 

常用的Field方法如下:

方法

切词

索引

存储

用途

Field.Text(String name, String value)

Y

Y

Y

标题,文章内容

Field.Text(String name, Reader value)

Y

Y

N

META信息

Field.Keyword(String name, String value)

N

Y

Y

作者

Field.UnIndexed(String name, String value)

N

N

Y

文件路径

Field.UnStored(String name, String value)

Y

Y

N

与第二种类似

 

为了更深入的了解全文检索库,我们可以将全文检索库与通常的关系型数据库(如Oracle,Mysql)作一下对比。

 

全文检索库对关系型数据库对比

对比项

全文检索库(Lucene)

关系型数据库(Oracle)

核心功能

以文本检索为主,插入(insert)、删除(delete)、修改(update)比较麻烦,适合于大文本块的查询。

插入(insert)、删除(delete)、修改(update)十分方便,有专门的SQL命令,但对于大文本块(如CLOB)类型的检索效率低下。

与Oracle类似,都可以建多个库,且各个库的存储位置可以不同。

可以建多个库,每个库一般都有控制文件和数据文件等,比较复杂。

没有严格的表的概念,比如Lucene的表只是由入库时的定义字段松散组成。

有严格的表结构,有主键,有字段类型等。

记录

由于没有严格表的概念,所以记录体现为一个对象,在Lucene里记录对应的类是Document。

Record,与表结构对应。

字段

字段类型只有文本和日期两种,字段一般不支持运算,更无函数功能。

在Lucene里字段的类是Field,如document(field1,field2…)

字段类型丰富,功能强大。

record(field1,field2…)

查询结果集

在Lucene里表示查询结果集的类是Hits,如hits(doc1,doc2,doc3…)

在JDBC为例, Resultset(record1,record2,record3...)


两种库对比图如下:

 

检索源码及说明

 

QueryRecords.java

packagecom.holen.part1;

 

importjava.util.ArrayList;

importorg.apache.lucene.analysis.standard.StandardAnalyzer;

importorg.apache.lucene.document.Document;

importorg.apache.lucene.queryParser.QueryParser;

importorg.apache.lucene.search.Hits;

importorg.apache.lucene.search.IndexSearcher;

importorg.apache.lucene.search.Query;

importorg.apache.lucene.search.Searcher;

 

/**

 * @authorHolenChen

 *检索查询

 */

public classQueryRecords{

 

    publicQueryRecords(){

    }

   

    /**

     *检索查询,将结果集返回

     * @paramsearchkey

     * @paramdbpath

     * @paramsearchfield

     * @return

     */

    publicArrayListqueryRecords(Stringsearchkey,Stringdbpath,Stringsearchfield){

       ArrayListlist= null;

       try{

           Searchersearcher= newIndexSearcher(dbpath);

           Queryquery

            =QueryParser.parse(searchkey,searchfield,newStandardAnalyzer());

           Hitshits=searcher.search(query);

           if(hits!= null){

              list= newArrayList();

              inttemp_hitslength=hits.length();

              Documentdoc= null;

              for(inti=0;i<temp_hitslength;i++){

                  doc=hits.doc(i);

                  list.add(doc.get("filename"));

              }

           }

       }catch(Exceptionex){

           ex.printStackTrace();

       }

       returnlist;

    }

 

    public static voidmain(String[]args){

       QueryRecordstemp= newQueryRecords();      

       ArrayListlist= null;

       list=temp.queryRecords("holen","e:\\lucene\\holendb","content");

       for(inti=0;i<list.size();i++){

           System.out.println((String)list.get(i));

       }      

    }

}

 

 

说明:该类中Searcher负责查询,并把查询结果以Hits对象集方式返回,Hits好比JDBC中的RecordSet,Hits是Document的集合,每个Document相当于一条记录,Document中包含一个或多个字段,可以通过Document.get(“字段名”)方法得到每个字段的内容。

 

通过这三个类,就完成了一个简单的基于Lucene的全文检索应用。

 

4.总结

 

Lucene十分精练纯粹,就一个jar包,引入到你的工程中,调用其接口,就可以为你的应用增添全文检索功能。

 

通过上一节的初步应用会发现,Lucene使用起来很简单,与JDBC有些类似,应用时重点掌握好IndexWriter,Document,Field,Searcher等几个类即可。

 

Lucene的结构很清晰,每个package司职一项,比如org.apache.Lucene.search负责检索,org.apache.Lucene.index索引,org.apache.Lucene.analysis切词等,且Lucene的主要动作都采用了抽象类,扩展起来十分方便。

 

相对于一些商业化全文检索,Lucene的入库速度更快。因为它的存储采取分步合并的方法,先建立小索引,待时机成熟才把小索引合并到大索引树上。因此,我们在操作应用数据时可以同步进行全文检索库的操作而不会(或许很少)影响系统的效能。

 

Lucene性能稳定,使用简单,而且开源免费,有Apache基金在后面做支撑,资金和技术力量都十分雄厚,这两年也一直是稳步更新,每次新版本的推出,业界均争相报导。

 

参考资料

 

1.  Introduction to Text Indexing with Apache Jakarta Lucene(Otis Gospodnetic)

2.  Lucene Introduction in Chinese(车东)

3.  Lucene Tutorial(Steven J. Owens)

分享到:
评论

相关推荐

    lucene学习笔记

    标题:Lucene学习笔记 描述:Lucene学习笔记,Lucene入门必备材料 知识点: 一、Lucene概述与文档管理策略 Lucene是一款高性能、全功能的文本搜索引擎库,广泛应用于文档检索、全文搜索等场景。为了提升搜索效率...

    Lucene 学习笔记 1

    **Lucene 学习笔记 1** Lucene 是一个全文搜索引擎库,由 Apache 软件基金会开发。它提供了一个可扩展的、高性能的搜索框架,使得开发者能够在其应用程序中集成高级的搜索功能。本篇学习笔记将深入探讨 Lucene 的...

    Lucene学习笔记(一)Lucene入门实例

    NULL 博文链接:https://kylinsoong.iteye.com/blog/719415

    【大搜集:lucene学习资料】---<下载不扣分,回帖加1分,欢迎下载,童叟无欺>

    lucene学习笔记 1 .txt lucene学习笔记 2.txt lucene学习笔记 3 .txt lucene入门实战.txt Lucene 的学习 .txt Lucene-2.0学习文档 .txt Lucene入门与使用 .txt lucene性能.txt 大富翁全文索引和查询的例子...

    lucene学习资料

    10. **lucene学习笔记 3 .txt** 这是作者的学习笔记,可能包含了个人理解和使用Lucene过程中遇到的问题及解决方案,提供了不同角度的见解和实践经验。 通过这些文档,你可以系统地学习和掌握Lucene的各个方面,从...

    Lucene 3.6 学习笔记

    【Lucene 3.6 学习笔记】 Lucene 是一个高性能、全文本搜索库,广泛应用于各种搜索引擎的开发。本文将深入探讨Lucene 3.6版本中的关键概念、功能以及实现方法。 ### 第一章 Lucene 基础 #### 1.1 索引部分的核心...

    Lucene开发指南

    Lucene学习笔记(二)可能涉及索引构建过程,讲解了如何使用Document对象存储文档内容,Field对象定义字段属性,以及如何使用IndexWriter进行索引更新和优化。 笔记(三)和(四)可能深入到查询解析和执行。查询解析器...

    lucene3.5学习笔记

    ### Lucene 3.5 学习笔记 #### 一、Lucene 3.5 基本概念 ##### 1.1 Lucene 概述 **1.1.1 IndexWriter** `IndexWriter` 是 Lucene 中的核心类之一,用于创建或更新索引。它提供了添加文档、删除文档、优化索引等...

    基于lucene和nutch的开源搜索引擎资料集合

    Lucene学习笔记.doc nutch_tutorial.pdf nutch二次开发总结.txt nutch入门.pdf nutch入门学习.pdf Nutch全文搜索学习笔记.doc Yahoo的Hadoop教程.doc [硕士论文]_基于Lucene的Web搜索引擎实现.pdf [硕士论文]_基于...

    lunece 学习笔记实用知识库分享知识分享

    Lucene 学习笔记是指如何学习和使用 Lucene。我们可以通过学习 Lucene 的使用和实现来掌握 Lucene。 Solr 学习笔记 Solr 学习笔记是指如何学习和使用 Solr。我们可以通过学习 Solr 的使用和实现来掌握 Solr。 ...

    【分享:lucene学习资料】---<下载不扣分,回帖加1分,欢迎下载,童叟无欺>

    1&gt; lucene学习笔记 2&gt; 全文检索的实现机制 【1】lucene学习笔记的目录如下 1. 概述 3 2. lucene 的包结构 3 3. 索引文件格式 3 4. lucene中主要的类 4 4.1. Document文档类 4 4.1.1. 常用方法 4 4.1.2. 示例 4 4.2...

Global site tag (gtag.js) - Google Analytics