Lucene是一个可以为应用添加文本索引和检索功能的Java类库。它不是一个可以下载、安装、运行的完整应用, 它提供了一个简单但功能强大的核心API。你仅需要知道一些Lucene类和方法就可以踏上使用的道路了。
Lucene主要提供了两个服务:文本索引,文本检索。这两个功能互相相对独立,虽然索引不用说影响着检索。这篇文章我将专注于讲解文本索引,我们会看到提供文本索引功能的一些核心lucene类。
Lucene背景
Lucene最初是由Doug Cutting开发的,可以通过SourceForge(传说中的SF)下载到。作为服务器端的开源java产品于2001年9月份加入了apache软 件基金会的jakarta家族。从那时发布的每一个版本,这个项目都吸引了越来越多的用户和开发者。2002年11月Lucene Version1.2发布了,1.3版本开发中。通过那些标注为“Powered by Lucene”的组织,我听说了FedEx,Overture, Mayo Clinic, Hewlett Packard, New Scientist magazine, Epiphany等等正在使用,至少在评估Lucene。
Lucene安装
跟其他jakarta项目一样,Lucene以预编译二进制或源码的形式发布。从Lucene的发布页你可以下载到最新的Lucene版本。如果你喜欢使 用最新的特性,还有当日最新版提供。为了示范Lucene的用法,我假想大家都在使用预编译版本,直接下载Lucene.jar把它加入到你的 CLASSPATH环境变量中。如果你选择下载源码包,自己进行编译,那么你需要jakarta ant 和javaCC,这两个也是免费提供下载的。虽然开发javaCC的公司已经不存在了,你仍然可以从本文参考部分找到下载的
URL
Lucene索引
在转向代码之前,先让我们看一看Lucene用于文本索引的主要Java类,它们是IndexWriter,Analyzer,Document和 Field。IndexWriter用于创建新索引和添加文档到存在的索引中去。文本被索引之前,先被传递给Analyzer,Analyzers负责从 要索引的文本中提取可索引的令牌符号,把不可索引的剔除掉。Lucene有一些不同的Analyzer实现,其中的一些负责对无意义的终止字符(一些对区 分文档没有帮助的经常用到的诸如”a”,”an”,”the”,”in”,”the”等单词)
做跳过处理,一些负责把令牌词处理成小写,以便检索时可以做到大小写不敏感,还有一些其他的不赘述了。
索引是文档的集合,文档是字段的集合,每个字段有名称(key,键)和内容(value,值)。考虑到一个文档对应RDBMS(关系型数据库管理系统)中表的一行,一个字段对应表的那一行的某一列。
现在,让我们假定一个简单的场景,你有一些文本需要索引,这些文本存储在一个字符串实例变量中,下面我们使用一个java类来描述上述的场景。

import org.apache.lucene.index.IndexWriter;
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;

/**
 * LuceneIndexExample 类提供了一个简单的使用lucene进行索引的例子
 * 它在一个临时目录中创建了一个名称为"index-1"的新索引,
 * 每次调用向该索引中添加一个包含一个字段的文档
 */
public class LuceneIndexExample
{
    public static void main(String args[]) throws Exception
    {
        String text = "This is the text to index with Lucene";

        String indexDir =
            System.getProperty("java.io.tmpdir", "tmp") +
            System.getProperty("file.separator") + "index-1";
        Analyzer analyzer = new StandardAnalyzer();
        boolean createFlag = true;

        IndexWriter writer =
            new IndexWriter(indexDir, analyzer, createFlag);
        Document document  = new Document();
        document.add(Field.Text("fieldname", text));
        writer.addDocument(document);
        writer.close();
    }
}

让我们来安步分析这组代码,lucene将索引存储在硬盘的文件系统中,每个索引在一个单独的目录中存储,多个索引不能共享一个目录,IndexWriter构 造类的第一个参数指定了索引应该存储的目录,第二个参数提供了用来预处理存储前被索引的文本的Analizer类的实现类,Analyzer类的特殊实现 类消除噪音单词,转换令牌词为小写,并且对输入的文本进行细微的修饰(诸如从缩写字中消除周期),最后一个参数是个布尔变量,当为真(true)的时候, 告诉IndexWriter在指定的目录中创建新的索引或者覆盖已经存在的索引,如果为假(false)的时候,告诉IndexWriter不要添加文档 到一个已经存在的索引中。当我们创建一个新的空文档时,添加一个名称为fieldname的字段到文档中,包含一个我们将要索引的文本值。文档填充好以 后,使用IndexWriter的addDocument方法把它加入到索引中去,最后关闭IndexWriter实例,这一点很重要,因为它指示把索引 的改动保存到硬盘中。
分析器(Analyzers)
我在上文提到过,Analizer是对输入的文本进行预处理的部件。检索的时候也能用的到。因为搜索字符串也需要以处理索引文本的方式进行处理。对索引和检索来说,使用相同的Analyzer是很重要的,不同的Analyzer会导致得到不正确的结果。
Analyzer类是一个抽象类,但是Lucene提供了一些实现类以便对输入的文本进行不同的预处理。如果你要实现的索引文本和查询串预处理方式 Lucene没有提供,那么需要实现Analyzer类以便对需求自定义。例如,如果你要索引非拉丁语系的文本,就需要自定义Analyzer实现类。