Lucene教程(一 )

Lucene是一个基于JAVA的全文信息检索工具包,它不是一个完整的搜索应用程序,而是为你的应用程序提供索引和搜索功能。Lucene是ApacheJakarta家族中的一个开源项目。也是目前最为流行的基于JAVA开源全文检索工具包。

目前已经有很多应用程序的搜索功能是基于Lucene的,比如eclipse的帮助系统的搜索功能。Lucene能够为文本类型的数据建立索引,所以你只要能把你要索引的数据格式转化成文本的,Lucene就能对你的文档进行索引和搜索。

搜索应用程序和Lucene之间的关系



索引和搜索

索引是现代搜索引擎的核心,建立索引的过程就是把源数据处理成非常方便查询的索引文件的过程。

       建立索引的必要性:试想你现在要在大量的文档中搜索含有某个关键词的文档,那么如果不建立索引的话,则需要把这些文档顺序读入内存,然后检查这个文章中是不是含有要查找的关键词,非常耗时。搜索引擎之所以会在毫秒级的时间内查找出要搜索的结果,就是因为建立了索引。

索引是一种 数据结构,用于快速随机访问存储在索引中的关键词,进而找到该关键词所关联的文档。Lucene采用的是一种称为反向索引(inverted index)的机制。

反向索引就是说我们维护了一个词/短语表,对于这个表中的每个词/短语,都有一个链表描述了有哪些文档包含了这个词/短语。由于Lucene提供了简单易用的API,所以即使读者刚开始对全文本进行索引的机制并不太了解,也可以非常容易地实用Luene对你的文档实现索引。

对文档建立好索引后,就可以在这些索引上面进行搜索了。搜索引擎首先会对搜索的关键词进行解析,然后再在建立好的索引上面进行查找,最终返回和用户输入的关键词相关联的文档。


  Lucene软件包

  Lucene软件包的发布形式是一个JAR文件:

  (1)包名:org.apache.lucene.document

         提供了一些为封装要素索引的文档所需要的类,比如Document,Field。每个文档最终被封装为一个Document对象。

(2)包名:org.apache.lucene.analysis

  对文档进行分词。在文档建立索引之前需要进行分词,这个包的作用是为建立索引做准备。

(3)包名:org.apache.lucene.index

   提供了一些协助创建索引以及对创建好的索引进行更新的类。

内含两个基础类:IndexWriter和IndexReader,其中IndexWriter是用来创建索引并添加文档到索引中的;

  IndexReader是用来删除索引中的文档的。

(4)包名:org.apache.lucene.search

该包提供了搜索所需要的类。

比如IndexSearcher和Hits。其中IndexSearcher定义了在指定的索引上进行搜索的方法,Hits用来保存搜索得到的结果。

一个简单的搜索应用程序

  假设我们的电脑目录中含有很多文本文档,我们需要查找哪些文档含有某个关键词。首先,利用Lucene对这个目录中的文档建立索引,然后在建立好的索引中搜索我们所需要查找的文档。

建立索引需要五个类:Document、Feild、IndexWriter、Analyzer、Directory。

        (1)Document用来描述文档(比如,一个文本文件、一个HTML页面)。一个Document对象由多个Field对象组成,可以把一个Document对象想象成数据库中的一个记录,而每个Field对象就是记录的一个字段。

         (2)Field对象是用来描述一个文档的某个属性,比如一封电子邮件的标题和内容可以用两个Field对象分别描述。

         (3)Analyzer在一个文档被索引之前,首先要对文档内容进行分词处理。分词工作是由Analyzer来做的。Analyzer是一个抽象类,它有多个实现。针对不同的语言和应用要选择适合的Analyzer。Analyzer把分词后的内容交给IndexWriter来建立索引。

         (4)IndexWriter是Lucene用来创建索引的一个核心的类,它的作用是把一个个的Document对象加到索引中来。

  (5)Directory这个类代表了Lucene的索引的存储位置,这是一个抽象类,目前有两个实现,一个是FSDirectory,它表示一个存储在文件系统中的索引的位置。第二个是RAMDirectory,它表示一个存储在内存当中的索引的位置。

   

  对文本文件建立索引代码(代码如下):

package TestLucene; 
import java.io.File; 
import java.io.FileReader; 
import java.io.Reader; 
import java.util.Date; 
import org.apache.lucene.analysis.Analyzer; 
import org.apache.lucene.analysis.standard.StandardAnalyzer; 
import org.apache.lucene.document.Document; 
import org.apache.lucene.document.Field; 
import org.apache.lucene.index.IndexWriter; 
/** 
* This class demonstrate the process of creating index with Lucene 
* for text files 
*/ 
public class TxtFileIndexer { 
     public static void main(String[] args) throws Exception{ 
     //indexDir is the directory that hosts Lucene's index files 
     File   indexDir = new File("D:\\luceneIndex"); 
     //dataDir is the directory that hosts the text files that to be indexed 
     File   dataDir  = new File("D:\\luceneData"); 
     Analyzer luceneAnalyzer = new StandardAnalyzer(); 
     File[] dataFiles  = dataDir.listFiles(); 
     IndexWriter indexWriter = new IndexWriter(indexDir,luceneAnalyzer,true); 
     long startTime = new Date().getTime(); 
     for(int i = 0; i < dataFiles.length; i++){ 
          if(dataFiles[i].isFile() && dataFiles[i].getName().endsWith(".txt")){
               System.out.println("Indexing file " + dataFiles[i].getCanonicalPath()); 
               Document document = new Document(); 
               Reader txtReader = new FileReader(dataFiles[i]); 
               document.add(Field.Text("path",dataFiles[i].getCanonicalPath())); 
               document.add(Field.Text("contents",txtReader)); 
               indexWriter.addDocument(document); 
          } 
     } 
     indexWriter.optimize(); 
     indexWriter.close(); 
     long endTime = new Date().getTime(); 
        
     System.out.println("It takes " + (endTime - startTime) 
         + " milliseconds to create index for the files in directory "
         + dataDir.getPath());        
     } 
}


  以上代码的分析:

(1)IndexWriter的构造函数需要三个参数:第一个参数制定了所创建的索引要存放的位置,可以是个File对象,也可以是一个FSDirectory对象,或者是RAWDirectory对象;第二个参数制定了Analyzer类的一个实现,也就是指定这个索引是用哪个分词器对文档内容进行分词;第三个参数是一个布尔型的变量,如果为true的话就代表创建一个新的索引,为false的话就代表在原来索引的基础上进行操作。

(2)接着程序遍历了目录下面的所有文本文档,并为每一个文本文档创建了一个Document对象。然后把文本文档的两个属性:路径和内容加入到两个Field对象中,再把这两个Field对象加入到Document对象中,最后把这个文档用IndexWriter类的add方法加入到索引中去。

以上几步就完成了索引的创建。

       

        建立好索引后,进行搜索----搜索文档:

利用Lucene进行搜索就像建立索引一样也是非常方便的。上面已完成的工作:为一个目录下的文本文档建立索引。以下内容为:在这个索引上进行搜索以找到包含某个关键词或短语的文档。

Lucene提供了几个基础的类来完成这个过程,分别是:IndexSearcher、Term、Query、TermQuery、Hits,详细介绍如下:

(1)Query类

Query类是一个抽象类,它有多个实现,比如TermQuery、BooleanQuery、PrefixQuery。这个类用于:把用户输入的查询字符串封装成Lucene能够识别的Query。

(2)Term类

Term是搜索的基本单位,一个Term对象有两个String类型的域组成。

生成一个Term对象:Term term=new Term("fieldName","queryWord");其中第一个参数代表了要在文档中的哪一个Field上进行查找,第二个参数代表了要查询的关键词。

(3)TermQuery类

TermQuery类是抽象类Query的一个子类,它同时也是Lucene支持的最为基本的一个查询类。

生成一个TermQuery对象:TermQuery termQuery=new TermQuery(new Term("fieldName","queryWord"));它的构造函数只接收一个参数,那就是Term对象。

(4)IndexSearcher类

IndexSearcher是用来在建立好的索引上进行搜索的。它只能以只读的方式打开一个索引,所以可以有多个IndexSearcher的实例在一个索引上进行操作。

        (5)Hits类

Hits类是用来保存搜索结果的。


在建立好的索引上进行搜索(代码如下):

package TestLucene; 
 import java.io.File; 
 import org.apache.lucene.document.Document; 
 import org.apache.lucene.index.Term; 
 import org.apache.lucene.search.Hits; 
 import org.apache.lucene.search.IndexSearcher; 
 import org.apache.lucene.search.TermQuery; 
 import org.apache.lucene.store.FSDirectory; 
 /** 
 * This class is used to demonstrate the 
 * process of searching on an existing 
 * Lucene index 
 * 
 */ 
 public class TxtFileSearcher { 
	 public static void main(String[] args) throws Exception{ 
	    String queryStr = "lucene"; 
	    //This is the directory that hosts the Lucene index 
        File indexDir = new File("D:\\luceneIndex"); 
        FSDirectory directory = FSDirectory.getDirectory(indexDir,false); 
        IndexSearcher searcher = new IndexSearcher(directory); 
        if(!indexDir.exists()){ 
        	 System.out.println("The Lucene index is not exist"); 
        	 return; 
        } 
        Term term = new Term("contents",queryStr.toLowerCase()); 
        TermQuery luceneQuery = new TermQuery(term); 
        Hits hits = searcher.search(luceneQuery); 
        for(int i = 0; i < hits.length(); i++){ 
        	 Document document = hits.doc(i); 
        	 System.out.println("File: " + document.get("path")); 
        } 
	 } 
 }

代码解释:

  (1)IndexSearch的构造函数接收一个类型为Directory的对象,Directory是抽象类,具有:FSDirectory和RAMDirectory两个子类。

        (2)程序中传入一个FSDirectory对象作为其参数(该参数代表存储在磁盘上的一个索引位置)。

         构造函数执行完毕后,代表这个IndexSearcher以只读的方式带开了一个索引。

(3)然后,程序构造了一个Term对象,通过该Term对象 指定:在文档内容中搜索包含关键词“lucene”的文档。

(4)利用这个Term对象构造出TermQuery对象,并把这个TermQuery对象传入到IndexSearcher的search方法中进行查询,返回结果保存至Hits对象中。

        (5)用一个循环语句把搜索到的文档路径打印出来。


        至此,利用Lucene开发搜索应用程序已经搞定了。


        总结文章主要内容:Lucene基本概念、Lucene建立索引并在该索引上进行搜索的过程。

    

        原文链接:http://www.ibm.com/developerworks/cn/java/j-lo-lucene1/







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值