`

实战 Lucene,第 1 部分: 初识 Lucene

阅读更多

实战 Lucene,第 1 部分: 初识 Lucene

本文首先介绍了Lucene的一些基本概念,然后开发了一个应用程序演示了利用Lucene建立索引并在该索引上进行搜索的过程。

Lucene 简介

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

目前已经有很多应用程序的搜索功能是基于 Lucene 的,比如 Eclipse 的帮助系统的搜索功能。Lucene 能够为文本类型的数据建立索引,所以你只要能把你要索引的数据格式转化的文本的,Lucene 就能对你的文档进行索引和搜索。比如你要对一些 HTML 文档,PDF 文档进行索引的话你就首先需要把 HTML 文档和 PDF 文档转化成文本格式的,然后将转化后的内容交给 Lucene 进行索引,然后把创建好的索引文件保存到磁盘或者内存中,最后根据用户输入的查询条件在索引文件上进行查询。不指定要索引的文档的格式也使 Lucene 能够几乎适用于所有的搜索应用程序。

图 1 表示了搜索应用程序和 Lucene 之间的关系,也反映了利用 Lucene 构建搜索应用程序的流程:


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

 

 

 





回页首


索引和搜索

索引是现代搜索引擎的核心,建立索引的过程就是把源数据处理成非常方便查询的索引文件的过程。为什么索引这么重要呢,试想你现在要在大量的文档中搜索含有某个关键词的文档,那么如果不建立索引的话你就需要把这些文档顺序的读入内存,然后检查这个文章中是不是含有要查找的关键词,这样的话就会耗费非常多的时间,想想搜索引擎可是在毫秒级的时间内查找出要搜索的结果的。这就是由于建立了索引的原因,你可以把索引想象成这样一种数据结构,他能够使你快速的随机访问存储在索引中的关键词,进而找到该关键词所关联的文档。Lucene 采用的是一种称为反向索引(inverted index)的机制。反向索引就是说我们维护了一个词/短语表,对于这个表中的每个词/短语,都有一个链表描述了有哪些文档包含了这个词/短语。这样在用户输入查询条件的时候,就能非常快的得到搜索结果。我们将在本系列文章的第二部分详细介绍 Lucene 的索引机制,由于 Lucene 提供了简单易用的 API,所以即使读者刚开始对全文本进行索引的机制并不太了解,也可以非常容易的使用 Lucene 对你的文档实现索引。

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





回页首

Lucene 软件包分析

Lucene 软件包的发布形式是一个 JAR 文件,下面我们分析一下这个 JAR 文件里面的主要的 JAVA 包,使读者对之有个初步的了解。

Package: org.apache.lucene.document

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

Package: org.apache.lucene.analysis

这个包主要功能是对文档进行分词,因为文档在建立索引之前必须要进行分词,所以这个包的作用可以看成是为建立索引做准备工作。

Package: org.apache.lucene.index

这个包提供了一些类来协助创建索引以及对创建好的索引进行更新。这里面有两个基础的类:IndexWriter 和 IndexReader,其中 IndexWriter 是用来创建索引并添加文档到索引中的,IndexReader 是用来删除索引中的文档的。

Package: org.apache.lucene.search

这个包提供了对在建立好的索引上进行搜索所需要的类。比如 IndexSearcher 和 Hits, IndexSearcher 定义了在指定的索引上进行搜索的方法,Hits 用来保存搜索得到的结果。





回页首

一个简单的搜索应用程序

假设我们的电脑的目录中含有很多文本文档,我们需要查找哪些文档含有某个关键词。为了实现这种功能,我们首先利用 Lucene 对这个目录中的文档建立索引,然后在建立好的索引中搜索我们所要查找的文档。通过这个例子读者会对如何利用 Lucene 构建自己的搜索应用程序有个比较清楚的认识。





回页首

建立索引

为了对文档进行索引,Lucene 提供了五个基础的类,他们分别是 Document, Field, IndexWriter, Analyzer, Directory。下面我们分别介绍一下这五个类的用途:

Document

Document 是用来描述文档的,这里的文档可以指一个 HTML 页面,一封电子邮件,或者是一个文本文件。一个 Document 对象由多个 Field 对象组成的。可以把一个 Document 对象想象成数据库中的一个记录,而每个 Field 对象就是记录的一个字段。

Field

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

Analyzer

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

IndexWriter

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

Directory

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

熟悉了建立索引所需要的这些类后,我们就开始对某个目录下面的文本文件建立索引了,清单1给出了对某个目录下的文本文件建立索引的源代码。


清单 1. 对文本文件建立索引

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 对象或者 RAMDirectory 对象。第二个参数指定了 Analyzer 类的一个实现,也就是指定这个索引是用哪个分词器对文挡内容进行分词。第三个参数是一个布尔型的变量,如果为 true 的话就代表创建一个新的索引,为 false 的话就代表在原来索引的基础上进行操作。接着程序遍历了目录下面的所有文本文档,并为每一个文本文档创建了一个 Document 对象。然后把文本文档的两个属性:路径和内容加入到了两个 Field 对象中,接着在把这两个 Field 对象加入到 Document 对象中,最后把这个文档用 IndexWriter 类的 add 方法加入到索引中去。这样我们便完成了索引的创建。接下来我们进入在建立好的索引上进行搜索的部分。





回页首

搜索文档

利用Lucene进行搜索就像建立索引一样也是非常方便的。在上面一部分中,我们已经为一个目录下的文本文档建立好了索引,现在我们就要在这个索引上进行搜索以找到包含某个关键词或短语的文档。Lucene提供了几个基础的类来完成这个过程,它们分别是呢IndexSearcher, Term, Query, TermQuery, Hits. 下面我们分别介绍这几个类的功能。

Query

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

Term

Term是搜索的基本单位,一个Term对象有两个String类型的域组成。生成一个Term对象可以有如下一条语句来完成:Term term = new Term(“fieldName”,”queryWord”); 其中第一个参数代表了要在文档的哪一个Field上进行查找,第二个参数代表了要查询的关键词。

TermQuery

TermQuery是抽象类Query的一个子类,它同时也是Lucene支持的最为基本的一个查询类。生成一个TermQuery对象由如下语句完成: TermQuery termQuery = new TermQuery(new Term(“fieldName”,”queryWord”)); 它的构造函数只接受一个参数,那就是一个Term对象。

IndexSearcher

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

Hits

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

介绍完这些搜索所必须的类之后,我们就开始在之前所建立的索引上进行搜索了,清单2给出了完成搜索功能所需要的代码。


清单2 :在建立好的索引上进行搜索

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"));
        }
	}
}

在清单2中,类IndexSearcher的构造函数接受一个类型为Directory的对象,Directory是一个抽象类,它目前有两个子类:FSDirctory和RAMDirectory. 我们的程序中传入了一个FSDirctory对象作为其参数,代表了一个存储在磁盘上的索引的位置。构造函数执行完成后,代表了这个IndexSearcher以只读的方式打开了一个索引。然后我们程序构造了一个Term对象,通过这个Term对象,我们指定了要在文档的内容中搜索包含关键词”lucene”的文档。接着利用这个Term对象构造出TermQuery对象并把这个TermQuery对象传入到IndexSearcher的search方法中进行查询,返回的结果保存在Hits对象中。最后我们用了一个循环语句把搜索到的文档的路径都打印了出来。好了,我们的搜索应用程序已经开发完毕,怎么样,利用Lucene开发搜索应用程序是不是很简单。





回页首

总结

本文首先介绍了 Lucene 的一些基本概念,然后开发了一个应用程序演示了利用 Lucene 建立索引并在该索引上进行搜索的过程。希望本文能够为学习 Lucene 的读者提供帮助。


关于作者

 

周登朋,软件工程师,上海交通大学研究生,对 Java 技术以及信息检索技术很感兴趣。您可以通过 zhoudengpeng@yahoo.com.cn 与他联系。

分享到:
评论

相关推荐

    解密搜索引擎技术实战Lucene&Java精华版(2)

    关键词:Lucene solr 搜索引擎 Lucene实战 随书源码 本书随书光盘文件有1G,压缩后有&gt;400MB, 我单个文件的权限是80MB 故分为下面6个包上传: 解密搜索引擎技术实战Lucene&Java精华版(1) 解密搜索引擎技术实战Lucene&...

    IKAnalyzer中文分词支持lucene6.5.0版本

    由于林良益先生在2012之后未对IKAnalyzer进行更新,后续lucene分词接口发生变化,导致不可使用,所以此jar包支持lucene6.0以上版本

    解密搜索引擎技术实战Lucene&Java精华版(第3版)源码(4)-补第6章

    关键词:Lucene solr 搜索引擎 Lucene实战 随书源码 本书随书光盘文件有1G,压缩后有&gt;400MB, 我单个文件的权限是80MB 故分为下面6个包上传: 解密搜索引擎技术实战Lucene&Java精华版(第3版)源码(1) 解密搜索引擎技术...

    解密搜索引擎技术实战 LUCENE & JAVA(第3版)PDF

    《解密搜索引擎技术实战 LUCENE & JAVA(第3版)》是一本深入探讨搜索引擎技术的专业书籍,由罗刚撰写。这本书主要聚焦于LUCENE和JAVA这两种技术在搜索引擎开发中的应用,为读者揭示了搜索引擎背后的复杂机制和实现...

    解密搜索引擎技术实战Lucene&Java精华版(第3版)源码

    关键词:Lucene solr 搜索引擎 Lucene实战 随书源码 本书随书光盘文件有1G,压缩后有&gt;400MB, 我单个文件的权限是80MB 故分为下面6个包上传: 解密搜索引擎技术实战Lucene&Java精华版(1) 解密搜索引擎技术实战Lucene&...

    解密搜索引擎技术实战Lucene&Java精华版(5)

    关键词:Lucene solr 搜索引擎 Lucene实战 随书源码 本书随书光盘文件有1G,压缩后有&gt;400MB, 我单个文件的权限是80MB 故分为下面6个包上传: 解密搜索引擎技术实战Lucene&Java精华版(1) 解密搜索引擎技术实战Lucene&...

    lucene-core-7.7.0-API文档-中文版.zip

    赠送jar包:lucene-core-7.7.0.jar; 赠送原API文档:lucene-core-7.7.0-javadoc.jar; 赠送源代码:lucene-core-7.7.0-sources.jar; 赠送Maven依赖信息文件:lucene-core-7.7.0.pom; 包含翻译后的API文档:lucene...

    Lucene实战第二版中英文PDF(带书签)

    1. **Lucene简介**:Lucene是一个开源全文搜索引擎库,它提供了索引和搜索文本的基本工具,适用于各种项目,从小型到大型企业级应用。 2. **文档分析**:Lucene包含了强大的文档分析器,可以将输入的文本分解成有...

    解密搜索引擎技术实战Lucene&Java精华版(第3版)源码(6)-libp2

    关键词:Lucene solr 搜索引擎 Lucene实战 随书源码 本书随书光盘文件有1G,压缩后有&gt;400MB, 我单个文件的权限是80MB 故分为下面6个包上传: 解密搜索引擎技术实战Lucene&Java精华版(第3版)源码(1) 解密搜索引擎技术...

    解密搜索引擎技术实战Lucene&Java精华版(第3版)源码(3)-补第5章p2

    关键词:Lucene solr 搜索引擎 Lucene实战 随书源码 本书随书光盘文件有1G,压缩后有&gt;400MB, 我单个文件的权限是80MB 故分为下面6个包上传: 解密搜索引擎技术实战Lucene&Java精华版(第3版)源码(1) 解密搜索引擎技术...

    Lucene实战中文版第2版

    经典的Lucene资源

    Lucene实战(中文版第二版)对应Lucene版本

    1. **索引构建**:Lucene的核心功能之一就是快速构建倒排索引。这个版本中,你可以学习到如何通过`IndexWriter`类创建和更新索引,以及如何使用`Document`、`Field`来组织和存储文档内容。 2. **查询解析**:Lucene...

    解密搜索引擎技术实战:Lucene in java(第2版)源码 dvd ppt

    《解密搜索引擎技术实战:Lucene in java(第2版)源码 dvd ppt》是一部深入探讨搜索引擎技术的著作,特别关注于使用Java实现的开源全文搜索引擎库——Lucene。本书结合了理论与实践,旨在帮助读者理解搜索引擎的...

    Lucene实战(第二版)

    1. **全文检索**:Lucene的核心功能是支持高效的全文检索。它使用倒排索引来快速定位含有特定查询词的文档,这种索引结构能快速找到与查询匹配的文档。 2. **文本分析**:在建立索引之前,Lucene会对输入的文本进行...

    Lucene实战

    Lucene实战(第2版)(最权威的Lucene指南,覆盖Apache Lucene 3.0,作者为Lucene项目成员) 《Lucene实战(第2版)》基于Apache的Lucene 3.0,从Lucene核心、Lucene应用、案例分析3个方面详细系统地介绍了Lucene,包括...

    基于 SSM 框架的二手书交易系统.zip

    1. 运行环境 IDE:IntelliJ IDEA 项目构建工具:Maven 数据库:MySQL Tomcat:Tomcat 8.0.47 2. 初始化项目 创建一个名为bookshop的数据库,将bookshop.sql导入 打开IntelliJ IDEA,将项目导入 修改jdbc.properties...

    Lucene 3.0 原理与代码分析PDF

    Lucene学习总结之三:Lucene的索引文件格式(1) Lucene学习总结之三:Lucene的索引文件格式(2) Lucene学习总结之三:Lucene的索引文件格式(3) Lucene学习总结之四:Lucene索引过程分析(1) Lucene学习总结之...

    lucene实战第二版(最新)

    本书《Lucene实战第二版》是一本关于如何使用Lucene进行文本检索的实用教程。这本书详细介绍了Lucene的使用方法和内部工作机制,并提供了丰富的代码示例和清晰的解释。它不仅适合那些计划在应用中使用Lucene的开发者...

    Lucene的系统结构

    1. **Lucene的包结构** Lucene的核心功能分布于多个包中,每个包都有明确的职责: - `org.apache.lucene.analysis`: 提供语言分析器,负责文本的预处理,如分词。对于中文,通常需要使用特定的分词器,如IK ...

Global site tag (gtag.js) - Google Analytics