﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-joe --专注java,开源,架构,项目管理-随笔分类-lucene</title><link>http://www.blogjava.net/freeman1984/category/47431.html</link><description>         
        STANDING ON THE SHOULDERS OF GIANTS</description><language>zh-cn</language><lastBuildDate>Thu, 17 Feb 2011 15:50:01 GMT</lastBuildDate><pubDate>Thu, 17 Feb 2011 15:50:01 GMT</pubDate><ttl>60</ttl><item><title>使用 Apache Lucene 搜索文本（转自ibm）</title><link>http://www.blogjava.net/freeman1984/archive/2011/02/17/344555.html</link><dc:creator>@joe</dc:creator><author>@joe</author><pubDate>Thu, 17 Feb 2011 08:41:00 GMT</pubDate><guid>http://www.blogjava.net/freeman1984/archive/2011/02/17/344555.html</guid><wfw:comment>http://www.blogjava.net/freeman1984/comments/344555.html</wfw:comment><comments>http://www.blogjava.net/freeman1984/archive/2011/02/17/344555.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/freeman1984/comments/commentRss/344555.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/freeman1984/services/trackbacks/344555.html</trackback:ping><description><![CDATA[<p sizset="75" sizcache="22"><a name="N1005F"><span class="atitle">简介</span></a></p>
<p>Lucene 是一个开源、高度可扩展的搜索引擎库，可以从 Apache Software Foundation 获取。您可以将 Lucene 用于商业和开源应用程序。Lucene 强大的 API 主要关注文本索引和搜索。它可以用于为各种应用程序构建搜索功能，比如电子邮件客户端、邮件列表、Web 搜索、数据库搜索等等。Wikipedia、TheServerSide、jGuru 和 LinkedIn 等网站都使用了 Lucene。</p>
<p>Lucene 还为 Eclipse IDE、Nutch（著名的开源 Web 搜索引擎）以及 IBM&#174;、AOL 和 Hewlett-Packard 等公司提供搜索功能。Lucene 已经兼容许多其他编程语言，包括 Perl、Python、C++ 和 .NET。到 2009 年 7 月 30 日止，用于 Java&#8482; 编程语言的最新版 Lucene 为 V2.4.1。</p>
<p>Lucene 功能众多：</p>
<ul>
    <li>拥有强大、准确、有效的搜索算法。
    <li>计算每个文档匹配给定查询的分数，并根据分数返回最相关的文档。
    <li>支持许多强大的查询类型，比如 PhraseQuery、WildcardQuery、RangeQuery、FuzzyQuery、BooleanQuery 等。
    <li>支持解析人们输入的丰富查询表达式。
    <li>允许用户使用定制排序、过滤和查询表达式解析扩展搜索行为。
    <li>使用基于文件的锁定机制保护并发索引修改。
    <li>允许同时搜索和编制索引。 </li>
</ul>
<div class="ibm-alternate-rule">
<hr />
</div>
<p class="ibm-ind-link ibm-back-to-top" sizset="76" sizcache="22"><a class="ibm-anchor-up-link" href="#ibm-pcon">回页首</a></p>
<p sizset="77" sizcache="22"><a name="N1008A"><span class="atitle">使用 Lucene 构建应用程序</span></a></p>
<p>如图 1 所示，使用 Lucene 构建功能全面的搜索应用程序主要涉及编制数据索引、搜索数据和显示搜索结果几个方面。</p>
<br />
<a name="figure1"><strong>图 1. 使用 Lucene 构建应用程序的步骤</strong></a><br />
<img alt="使用 Lucene 构建应用程序的步骤" src="lucene.gif" width="404" height="406" /> <br />
<br />
<p>本文从使用 Lucene V2.4.1 和 Java 技术开发的样例应用程序中挑选了一些代码片段。示例应用程序为存储在属性文件中一组电子邮件文档编制索引，并展示了如何使用 Lucene 的查询 API 搜索索引。该示例还让您熟悉基本的索引操作。</p>
<div class="ibm-alternate-rule">
<hr />
</div>
<p class="ibm-ind-link ibm-back-to-top" sizset="79" sizcache="22"><a class="ibm-anchor-up-link" href="#ibm-pcon">回页首</a></p>
<p sizset="80" sizcache="22"><a name="N100A7"><span class="atitle">为数据编制索引</span></a></p>
<p>Lucene 允许您为任何文本格式的数据编制索引。Lucene 可以用于几乎任何数据源以及从中提取的文本信息。您可以使用 Lucene 编制索引并搜索 HTML 文档、Microsoft&#174; Word 文档、PDF 文件中存储的数据。编制数据索引的第一步是让数据变成一个简单的文本格式。您可以使用定制解析器和数据转换器实现这一点。</p>
<p sizset="81" sizcache="22"><a name="N100B2"><span class="smalltitle">编制索引的过程</span></a></p>
<p><em>编制索引</em> 是将文本数据转换为有利于快速搜索的格式。这类似于书本后面的索引：为您指出主题在书中出现的位置。</p>
<p>Lucene 将输入数据存储在名为<em>逆序</em> 索引的数据结构中, 该数据结构以索引文件集的形式存储在文件系统或内存中。大部分 Web 搜索引擎都使用逆序索引。它允许用户执行快速关键字查询，查找匹配给定查询的文档。在将文本数据添加到索引前，由分析程序（使用分析过程）进行处理。</p>
<p sizset="82" sizcache="22"><a name="N100C3"><span class="smalltitle">分析</span></a></p>
<p><em>分析</em> 是将文本数据转换为搜索基本单位（称为<em>项（term）</em>）的过程。在分析过程中，文本数据将经历多项操作：提取单词、移除通用单词、忽略标点符号、将单词变为词根形式、将单词变成小写等等。分析过程发生在编制索引和查询解析之前。分析将文本数据转换为标记，这些标记将作为项添加到 Lucene 索引中。</p>
<p>Lucene 有多种内置分析程序，比如 SimpleAnalyzer、StandardAnalyzer、StopAnalyzer、SnowballAnalyzer 等。它们在标记文本和应用过滤器的方式上有所区别。因为分析在编制索引之前移除单词，它减少了索引的大小，但是不利用精确的查询过程。您可以使用 Lucene 提供的基本构建块创建定制分析程序，以自己的方式控制分析过程。表 1 展示了一些内置分析程序及其处理数据的方式。</p>
<br />
<a name="table1"><strong>表 1. Lucene 的内置分析程序</strong></a><br />
<table class="ibm-data-table" border="0" cellspacing="0" summary="Lucene's in built analyzers" cellpadding="0" sizset="0" sizcache="2">
    <tbody sizset="0" sizcache="1">
        <tr jquery1297905857171="2">
            <th scope="col">分析程序</th>
            <th scope="col">对文本数据的操作</th>
        </tr>
        <tr jquery1297905857171="3">
            <td>WhitespaceAnalyzer</td>
            <td>分解空白处的标记</td>
        </tr>
        <tr jquery1297905857171="4">
            <td>SimpleAnalyzer </td>
            <td>分解非字母字符的文本，并将文本转为小写形式</td>
        </tr>
        <tr jquery1297905857171="5">
            <td>StopAnalyzer </td>
            <td>移除虚字（stop word）—— 对检索无用的字，并将文本转为小写形式</td>
        </tr>
        <tr jquery1297905857171="6">
            <td>StandardAnalyzer </td>
            <td>根据一种复杂语法（识别电子邮件地址、缩写、中文、日文、韩文字符、字母数字等等）标记文本<br />
            将文本转为小写形式<br />
            移除虚字</td>
        </tr>
    </tbody>
</table>
<p sizset="84" sizcache="22"><a name="N10116"><span class="smalltitle">核心索引编制类</span></a></p>
<dl sizset="85" sizcache="22">
<dt><strong><code>Directory</code></strong>
<dd>表示索引文件存储位置的抽象类。有两个常用的子类：
<ul>
    <li><code>FSDirectory</code> — 在实际文件系统中存储索引的 <code>Directory</code> 实现。该类对于大型索引非常有用。
    <li><code>RAMDirectory</code> — 在内存中存储所有索引的实现。该类适用于较小的索引，可以完整加载到内存中，在应用程序终止之后销毁。由于索引保存在内存中，所以速度相对较快。 </li>
</ul>
<dt><strong><code>Analyzer</code></strong>
<dd>正如上文所述，分析程序负责处理文本数据并将其转换为标记存储在索引中。在编制索引前，<code>IndexWriter</code> 接收用于标记数据的分析程序。要为文本编制索引，您应该使用适用于该文本语言的分析程序。
<p>默认分析程序适用于英语。在 Lucene 沙盒中还有其他分析程序，包括用于中文、日文和韩文的分析程序。</p>
<dt><strong><code>IndexDeletionPolicy</code></strong>
<dd>该接口用来实现从索引目录中定制删除过时提交的策略。默认删除策略是 <code>KeepOnlyLastCommitDeletionPolicy</code>，该策略仅保留最近的提交，并在完成一些提交之后立即移除所有之前的提交。
<dt><strong><code>IndexWriter</code></strong>
<dd sizset="85" sizcache="22">创建或维护索引的类。它的构造函数接收布尔值，确定是否创建新索引，或者打开现有索引。它提供在索引中添加、删除和更新文档的方法。
<p>对索引所做的更改最初缓存在内存中，并周期性转储到索引目录。<code>IndexWriter</code> 公开了几个控制如何在内存中缓存索引并写入磁盘的字段。对索引的更改对于 <code>IndexReader</code> 不可见，除非调用 <code>IndexWriter</code> 的提交或关闭方法。<code>IndexWriter</code> 创建一个目录锁定文件，以通过同步索引更新保护索引不受破坏。<code>IndexWriter</code> 允许用户指定可选索引删除策略。</p>
<br />
<a name="listing1"><strong>列表 1. 使用 Lucene <code>IndexWriter</code> </strong></a><br />
<table border="0" cellspacing="0" cellpadding="0" width="100%" sizset="5" sizcache="2">
    <tbody sizset="5" sizcache="1">
        <tr>
            <td class="code-outline">
            <pre class="displaycodeliquid">
            //Create instance of Directory where index files will be stored
            Directory fsDirectory =  FSDirectory.getDirectory(indexDirectory);
            /* Create instance of analyzer, which will be used to tokenize
            the input data */
            Analyzer standardAnalyzer = new StandardAnalyzer();
            //Create a new index
            boolean create = true;
            //Create the instance of deletion policy
            IndexDeletionPolicy deletionPolicy = new KeepOnlyLastCommitDeletionPolicy();
            indexWriter =new IndexWriter(fsDirectory,standardAnalyzer,create,
            deletionPolicy,IndexWriter.MaxFieldLength.UNLIMITED);
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
</dd></dl>
<p sizset="86" sizcache="22"><a name="N10185"><span class="smalltitle">将数据添加到索引</span></a></p>
<p>将文本数据添加到索引涉及到两个类。</p>
<p><code>Field</code> 表示搜索中查询或检索的数据片。<code>Field</code> 类封装一个字段名称及其值。Lucene 提供了一些选项来指定字段是否需要编制索引或分析，以及值是否需要存储。这些选项可以在创建字段实例时传递。下表展示了 <code>Field</code> 元数据选项的详细信息。 </p>
<br />
<a name="table1"><strong>表 2. <code>Field</code> 元数据选项的详细信息</strong></a><br />
<table class="ibm-data-table" border="0" cellspacing="0" summary="Details of Field metadata options" cellpadding="0" sizset="6" sizcache="2">
    <tbody sizset="6" sizcache="1">
        <tr jquery1297905857171="7">
            <th scope="col">选项</th>
            <th scope="col">描述</th>
        </tr>
        <tr jquery1297905857171="8">
            <td>Field.Store.Yes</td>
            <td>用于存储字段值。适用于显示搜索结果的字段 — 例如，文件路径和 URL。</td>
        </tr>
        <tr jquery1297905857171="9">
            <td>Field.Store.No</td>
            <td>没有存储字段值 — 例如，电子邮件消息正文。</td>
        </tr>
        <tr jquery1297905857171="10">
            <td>Field.Index.No</td>
            <td>适用于未搜索的字段 — 仅用于存储字段，比如文件路径。</td>
        </tr>
        <tr jquery1297905857171="11">
            <td>Field.Index.ANALYZED</td>
            <td>用于字段索引和分析 — 例如，电子邮件消息正文和标题。</td>
        </tr>
        <tr jquery1297905857171="12">
            <td>Field.Index.NOT_ANALYZED</td>
            <td>用于编制索引但不分析的字段。它在整体中保留字段的原值 — 例如，日期和个人名称。 </td>
        </tr>
    </tbody>
</table>
<p><code>Document</code> 是一个字段集合。Lucene 也支持推进文档和字段，这在给某些索引数据赋予重要性时非常有用。给文本文件编制索引包括将文本数据封装在字段中、创建文档、填充字段，使用 <code>IndexWriter</code> 向索引添加文档。</p>
<p>列表 2 展示向索引添加数据的示例。</p>
<br />
<a name="listing2"><strong>列表 2. 向索引添加数据</strong></a><br />
<table border="0" cellspacing="0" cellpadding="0" width="100%" sizset="12" sizcache="2">
    <tbody sizset="12" sizcache="1">
        <tr>
            <td class="code-outline">
            <pre class="displaycode">
            /*Step 1. Prepare the data for indexing. Extract the data. */
            String sender = properties.getProperty("sender");
            String date = properties.getProperty("date");
            String subject = properties.getProperty("subject");
            String message = properties.getProperty("message");
            String emaildoc = file.getAbsolutePath();
            /* Step 2. Wrap the data in the Fields and add them to a Document */
            Field senderField =
            new Field("sender",sender,Field.Store.YES,Field.Index.NOT_ANALYZED);
            Field emaildatefield =
            new Field("date",date,Field.Store.NO,Field.Index.NOT_ANALYZED);
            Field subjectField =
            new Field("subject",subject,Field.Store.YES,Field.Index.ANALYZED);
            Field messagefield =
            new Field("message",message,Field.Store.NO,Field.Index.ANALYZED);
            Field emailDocField =
            new Field("emailDoc",emaildoc,Field.Store.YES,
            Field.Index.NO);
            Document doc = new Document();
            // Add these fields to a Lucene Document
            doc.add(senderField);
            doc.add(emaildatefield);
            doc.add(subjectField);
            doc.add(messagefield);
            doc.add(emailDocField);
            //Step 3: Add this document to Lucene Index.
            indexWriter.addDocument(doc);
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<div class="ibm-alternate-rule">
<hr />
</div>
<p class="ibm-ind-link ibm-back-to-top" sizset="89" sizcache="22"><a class="ibm-anchor-up-link" href="#ibm-pcon">回页首</a></p>
<p sizset="90" sizcache="22"><a name="N10208"><span class="atitle">搜索索引数据</span></a></p>
<p>搜索是在索引中查找单词并查找包含这些单词的文档的过程。使用 Lucene 的搜索 API 构建的搜索功能非常简单明了。本小节讨论 Lucene 搜索 API 的主要类。</p>
<p sizset="91" sizcache="22"><a name="N10211"><span class="smalltitle">Searcher</span></a></p>
<p><code>Searcher</code> 是一个抽象基类，包含各种超负荷搜索方法。<code>IndexSearcher</code> 是一个常用的子类，允许在给定的目录中存储搜索索引。<code>Search</code> 方法返回一个根据计算分数排序的文档集合。Lucene 为每个匹配给定查询的文档计算分数。<code>IndexSearcher</code> 是线程安全的；一个实例可以供多个线程并发使用。</p>
<p sizset="92" sizcache="22"><a name="N10229"><span class="smalltitle">Term</span></a></p>
<p><em>Term</em> 是搜索的基本单位。它由两部分组成：单词文本和出现该文本的字段的名称。Term 对象也涉及索引编制，但是可以在 Lucene 内部创建。</p>
<p sizset="93" sizcache="22"><a name="N10234"><span class="smalltitle">Query 和子类</span></a></p>
<p><code>Query</code> 是一个用于查询的抽象基类。搜索指定单词或词组涉及到在项中包装它们，将项添加到查询对象，将查询对象传递到 <code>IndexSearcher</code> 的搜索方法。</p>
<p>Lucene 包含各种类型的具体查询实现，比如 TermQuery、BooleanQuery、PhraseQuery、PrefixQuery、RangeQuery、MultiTermQuery、FilteredQuery、SpanQuery 等。以下部分讨论 Lucene 查询 API 的主查询类。</p>
<dl sizset="94" sizcache="22">
<dt><strong><code>TermQuery</code></strong>
<dd sizset="94" sizcache="22">搜索索引最基本的查询类型。可以使用单个项构建 <code>TermQuery</code>。项值应该区分大小写，但也并非全是如此。注意，传递的搜索项应该与文档分析得到的项一致，因为分析程序在构建索引之前对原文本执行许多操作。
<p>例如，考虑电子邮件标题 &#8220;Job openings for Java Professionals at Bangalore&#8221;。假设您使用 <code>StandardAnalyzer</code> 编制索引。现在如果我们使用 <code>TermQuery</code> 搜索 &#8220;Java&#8221;，它不会返回任何内容，因为本文本应该已经规范化，并通过 <code>StandardAnalyzer</code> 转成小写。如果搜索小写单词 &#8220;java&#8221;，它将返回所有标题字段中包含该单词的邮件。</p>
<br />
<a name="listing3"><strong>列表 3. 使用 <code>TermQuery</code> 搜索</strong></a><br />
<table border="0" cellspacing="0" cellpadding="0" width="100%" sizset="13" sizcache="2">
    <tbody sizset="13" sizcache="1">
        <tr>
            <td class="code-outline">
            <pre class="displaycodeliquid">
            //Search mails having the word "java" in the subject field
            Searcher indexSearcher = new IndexSearcher(indexDirectory);
            Term term = new Term("subject","java");
            Query termQuery = new TermQuery(term);
            TopDocs topDocs = indexSearcher.search(termQuery,10);
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<dt><strong><code>RangeQuery</code></strong>
<dd sizset="95" sizcache="22">您可以使用 <code>RangeQuery</code> 在某个范围内搜索。索引中的所有项都以字典顺序排列。Lucene 的 <code>RangeQuery</code> 允许用户在某个范围内搜索项。该范围可以使用起始项和最终项（包含两端或不包含两端均可）指定。 <br />
<a name="listing4"><strong>列表 4. 在某个范围内搜索</strong></a><br />
<table border="0" cellspacing="0" cellpadding="0" width="100%" sizset="14" sizcache="2">
    <tbody sizset="14" sizcache="1">
        <tr>
            <td class="code-outline">
            <pre class="displaycodeliquid">
            /* RangeQuery example:Search mails from 01/06/2009 to 6/06/2009
            both inclusive */
            Term begin = new Term("date","20090601");
            Term end = new Term("date","20090606");
            Query query = new RangeQuery(begin, end, true);
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<dt><strong><code>PrefixQuery</code></strong>
<dd sizset="96" sizcache="22">您可以使用 <code>PrefixQuery</code> 通过前缀单词进行搜索，该方法用于构建一个查询，该查询查找包含以指定单词前缀开始的词汇的文档。 <br />
<a name="listing5"><strong>列表 5. 使用 <code>PrefixQuery</code> 搜索</strong></a><br />
<table border="0" cellspacing="0" cellpadding="0" width="100%" sizset="15" sizcache="2">
    <tbody sizset="15" sizcache="1">
        <tr>
            <td class="code-outline">
            <pre class="displaycodeliquid">
            //Search mails having sender field prefixed by the word 'job'
            PrefixQuery prefixQuery = new PrefixQuery(new Term("sender","job"));
            PrefixQuery query = new PrefixQuery(new Term("sender","job"));
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<dt><strong><code>BooleanQuery</code></strong>
<dd sizset="97" sizcache="22">您可以使用 <code>BooleanQuery</code> 组合任何数量的查询对象，构建强大的查询。它使用 <code>query</code> 和一个关联查询的子句，指示查询是应该发生、必须发生还是不得发生。在 <code>BooleanQuery</code> 中，子句的最大数量默认限制为 1,024。您可以调用 <code>setMaxClauseCount</code> 方法设置最大子句数。 <br />
<a name="listing6"><strong>列表 6. 使用 <code>BooleanQuery</code> 进行搜索</strong></a><br />
<table border="0" cellspacing="0" cellpadding="0" width="100%" sizset="16" sizcache="2">
    <tbody sizset="16" sizcache="1">
        <tr>
            <td class="code-outline">
            <pre class="displaycodeliquid">
            // Search mails have both 'java' and 'bangalore' in the subject field
            Query query1 = new TermQuery(new Term("subject","java"));
            Query query2 = new TermQuery(new Term("subject","bangalore"));
            BooleanQuery query = new BooleanQuery();
            query.add(query1,BooleanClause.Occur.MUST);
            query.add(query2,BooleanClause.Occur.MUST);
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<dt><strong><code>PhraseQuery</code></strong>
<dd sizset="98" sizcache="22">您可以使用 <code>PhraseQuery</code> 进行短语搜索。<code>PhraseQuery</code> 匹配包含特定单词序列的文档。<code>PhraseQuery</code> 使用索引中存储的项的位置信息。考虑匹配的项之间的距离称为 <em>slop</em>。默认情况下，slop 的值为零，这可以通过调用 <code>setSlop</code> 方法进行设置。<code>PhraseQuery</code> 还支持多个项短语。 <br />
<a name="listing7"><strong>列表 7. 使用 <code>PhraseQuery</code> 进行搜索</strong></a><br />
<table border="0" cellspacing="0" cellpadding="0" width="100%" sizset="17" sizcache="2">
    <tbody sizset="17" sizcache="1">
        <tr>
            <td class="code-outline">
            <pre class="displaycodeliquid">
            /* PhraseQuery example: Search mails that have phrase 'job opening j2ee'
            in the subject field.*/
            PhraseQuery query = new PhraseQuery();
            query.setSlop(1);
            query.add(new Term("subject","job"));
            query.add(new Term("subject","opening"));
            query.add(new Term("subject","j2ee"));
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<dt><strong><code>WildcardQuery</code></strong>
<dd sizset="99" sizcache="22"><code>WildcardQuery</code> 实现通配符搜索查询，这允许您搜索 arch*（可以查找包含 architect、architecture 等）之类的单词。使用两个标准通配符：
<ul>
    <li><code>*</code> 表示零个以上
    <li><code>?</code> 表示一个以上</li>
</ul>
如果使用以通配符查询开始的模式进行搜索，则可能会引起性能的降低，因为这需要查询索引中的所有项以查找匹配文档。 <br />
<a name="listing8"><strong>列表 8. 使用 WildcardQuery 进行搜索</strong></a><br />
<table border="0" cellspacing="0" cellpadding="0" width="100%" sizset="18" sizcache="2">
    <tbody sizset="18" sizcache="1">
        <tr>
            <td class="code-outline">
            <pre class="displaycodeliquid">
            //Search for 'arch*' to find e-mail messages that have word 'architect' in the subject
            field./
            Query query = new WildcardQuery(new Term("subject","arch*"));
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<dt><strong><code>FuzzyQuery</code></strong>
<dd sizset="100" sizcache="22">您可以使用 <code>FuzzyQuery</code> 搜索类似项，该类匹配类似于指定单词的单词。类似度测量基于 Levenshtein（编辑距离）算法进行。在列表 9 中，<code>FuzzyQuery</code> 用于查找与拼错的单词 &#8220;admnistrtor&#8221; 最接近的项，尽管这个错误单词没有索引。 <br />
<a name="listing9"><strong>列表 9. 使用 <code>FuzzyQuery</code> 进行搜索</strong></a><br />
<table border="0" cellspacing="0" cellpadding="0" width="100%" sizset="19" sizcache="2">
    <tbody sizset="19" sizcache="1">
        <tr>
            <td class="code-outline">
            <pre class="displaycodeliquid">
            /* Search for emails that have word similar to 'admnistrtor' in the
            subject field. Note we have misspelled admnistrtor here.*/
            Query query = new FuzzyQuery(new Term("subject", "admnistrtor"));
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<dt><strong><code>QueryParser</code></strong>
<dd sizset="101" sizcache="22"><code>QueryParser</code> 对于解析人工输入的查询字符非常有用。您可以使用它将用户输入的查询表达式解析为 Lucene 查询对象，这些对象可以传递到 <code>IndexSearcher</code> 的搜索方法。它可以解析丰富的查询表达式。 <code>QueryParser</code> 内部将人们输入的查询字符串转换为一个具体的查询子类。您需要使用反斜杠（<code>\</code>）将 <code>*</code>、<code>?</code> 等特殊字符进行转义。您可以使用运算符 <code>AND</code>、<code>OR</code> 和 <code>NOT</code> 构建文本布尔值查询。 <br />
<a name="listing10"><strong>列表 10. 搜索人工输入的查询表达式</strong></a><br />
<table border="0" cellspacing="0" cellpadding="0" width="100%" sizset="20" sizcache="2">
    <tbody sizset="20" sizcache="1">
        <tr>
            <td class="code-outline">
            <pre class="displaycodeliquid">QueryParser queryParser = new QueryParser("subject",new StandardAnalyzer());
            // Search for emails that contain the words 'job openings' and '.net' and 'pune'
            Query query = queryParser.parse("job openings AND .net AND pune");
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
</dd></dl>
<div class="ibm-alternate-rule">
<hr />
</div>
<p class="ibm-ind-link ibm-back-to-top" sizset="102" sizcache="22"><a class="ibm-anchor-up-link" href="#ibm-pcon">回页首</a></p>
<p sizset="103" sizcache="22"><a name="N10374"><span class="atitle">显示搜索结果</span></a></p>
<p><code>IndexSearcher</code> 返回一组对分级搜索结果（如匹配给定查询的文档）的引用。您可以使用 <code>IndexSearcher</code> 的搜索方法确定需要检索的最优先搜索结果数量。可以在此基础上构建定制分页。您可以添加定制 Web 应用程序或桌面应用程序来显示搜索结果。检索搜索结果涉及的主要类包括 <code>ScoreDoc</code> 和 <code>TopDocs</code>。</p>
<dl>
<dt><strong><code>ScoreDoc</code></strong>
<dd>搜索结果中包含一个指向文档的简单指针。这可以封装文档索引中文档的位置以及 Lucene 计算的分数。
<dt><strong><code>TopDocs</code></strong>
<dd>封装搜索结果以及 <code>ScoreDoc</code> 的总数。 </dd></dl>
<p>以下代码片段展示了如何检索搜索结果中包含的文档。</p>
<br />
<a name="listing11"><strong>列表 11. 展示搜索结果 </strong></a><br />
<table border="0" cellspacing="0" cellpadding="0" width="100%" sizset="21" sizcache="2">
    <tbody sizset="21" sizcache="1">
        <tr>
            <td class="code-outline">
            <pre class="displaycode">/* First parameter is the query to be executed and
            second parameter indicates the no of search results to fetch */
            TopDocs topDocs = indexSearcher.search(query,20);
            System.out.println("Total hits "+topDocs.totalHits);
            // Get an array of references to matched documents
            ScoreDoc[] scoreDosArray = topDocs.scoreDocs;
            for(ScoreDoc scoredoc: scoreDosArray){
            //Retrieve the matched document and show relevant details
            Document doc = indexSearcher.doc(scoredoc.doc);
            System.out.println("\nSender: "+doc.getField("sender").stringValue());
            System.out.println("Subject: "+doc.getField("subject").stringValue());
            System.out.println("Email file location: "
            +doc.getField("emailDoc").stringValue());
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p sizset="105" sizcache="22"><a name="N103B1"><span class="atitle">基本的索引操作</span></a></p>
<p>基本的索引操作包括移除和提升文档。</p>
<p sizset="106" sizcache="22"><a name="N103BA"><span class="smalltitle">从索引中移除文档</span></a></p>
<p>应用程序常常需要使用最新的数据更新索引并移除较旧的数据。例如，在 Web 搜索引擎中，索引需要定期更新，因为总是需要添加新网页，移除不存在的网页。Lucene 提供了 <code>IndexReader</code> 接口允许您对索引执行这些操作。</p>
<p><code>IndexReader</code> 是一个提供各种方法访问索引的抽象类。Lucene 内部引用文档时使用文档编号，该编号可以在向索引添加或从中移除文档时更改。文档编号用于访问索引中的文档。<code>IndexReader</code> 不得用于更新目录中的索引，因为已经打开了 <code>IndexWriter</code>。<code>IndexReader</code> 在打开时总是搜索索引的快照。对索引的任何更改都可以看到，直到再次打开 <code>IndexReader</code>。使用 Lucene 重新打开它们的 <code>IndexReader</code> 可以看到最新的索引更新。 </p>
<br />
<a name="listing12"><strong>列表 12. 从索引中删除文档</strong></a><br />
<table border="0" cellspacing="0" cellpadding="0" width="100%" sizset="22" sizcache="2">
    <tbody sizset="22" sizcache="1">
        <tr>
            <td class="code-outline">
            <pre class="displaycode">// Delete all the mails from the index received in May 2009.
            IndexReader indexReader = IndexReader.open(indexDirectory);
            indexReader.deleteDocuments(new Term("month","05"));
            //close associate index files and save deletions to disk
            indexReader.close();
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p sizset="108" sizcache="22"><a name="N103EC"><span class="smalltitle">提升文档和字段</span></a></p>
<p>有时您需要给某些索引数据更高的重要级别。您可以通过设置文档或字段的提升因子实现这一点。默认情况下，所有文档和字段的默认提升因子都是 1.0。</p>
<br />
<a name="listing13"><strong>列表 13. 提升字段</strong></a><br />
<table border="0" cellspacing="0" cellpadding="0" width="100%" sizset="23" sizcache="2">
    <tbody sizset="23" sizcache="1">
        <tr>
            <td class="code-outline">
            <pre class="displaycode">if(subject.toLowerCase().indexOf("pune") != -1){
            // Display search results that contain pune in their subject first by setting boost factor
            subjectField.setBoost(2.2F);
            }
            //Display search results that contain 'job' in their sender email address
            if(sender.toLowerCase().indexOf("job")!=-1){
            luceneDocument.setBoost(2.1F);
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<div class="ibm-alternate-rule">
<hr />
</div>
<p class="ibm-ind-link ibm-back-to-top" sizset="110" sizcache="22"><a class="ibm-anchor-up-link" href="#ibm-pcon">回页首</a></p>
<p sizset="111" sizcache="22"><a name="N103FE"><span class="atitle">扩展搜索</span></a></p>
<p>Lucene 提供一个称为<em>排序</em> 的高级功能。您可以根据指示文档在索引中相对位置的字段对搜索结果进行排序。用于排序的字段必须编制索引但不得标记。搜索字段中可以放入 4 种可能的项值：整数值、long 值、浮点值和字符串。</p>
<p>还可以通过索引顺序排序搜索结果。Lucene 通过降低相关度（比如默认的计算分数）对结果排序。排序的顺序是可以更改的。</p>
<br />
<a name="listing14"><strong>列表 14. 排序搜索结果</strong></a><br />
<table border="0" cellspacing="0" cellpadding="0" width="100%" sizset="24" sizcache="2">
    <tbody sizset="24" sizcache="1">
        <tr>
            <td class="code-outline">
            <pre class="displaycode">/* Search mails having the word 'job' in subject and return results
            sorted by sender's email in descending order.
            */
            SortField sortField = new SortField("sender", true);
            Sort sortBySender = new Sort(sortField);
            WildcardQuery query = new WildcardQuery(new Term("subject","job*"));
            TopFieldDocs topFieldDocs =
            indexSearcher.search(query,null,20,sortBySender);
            //Sorting by index order
            topFieldDocs = indexSearcher.search(query,null,20,Sort.INDEXORDER);
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p><em>Filtering</em> 是限制搜索空间，只允许某个文档子集作为搜索范围的过程。您可以使用该功能实现对搜索结果进行再次搜索，或者在搜索结果上实现安全性。Lucene 带有各种内置的过滤器，比如 BooleanFilter、CachingWrapperFilter、ChainedFilter、DuplicateFilter、PrefixFilter、QueryWrapperFilter、RangeFilter、RemoteCachingWrapperFilter、SpanFilter 等。<code>Filter</code> 可以传递到 <code>IndexSearcher</code> 的搜索方法，以过滤匹配筛选标准的筛选文档。</p>
<br />
<a name="listing15"><strong>列表 15. 筛选搜索结果</strong></a><br />
<table border="0" cellspacing="0" cellpadding="0" width="100%" sizset="25" sizcache="2">
    <tbody sizset="25" sizcache="1">
        <tr>
            <td class="code-outline">
            <pre class="displaycode">/*Filter the results to show only mails that have sender field
            prefixed with 'jobs' */
            Term prefix = new Term("sender","jobs");
            Filter prefixFilter = new PrefixFilter(prefix);
            WildcardQuery query = new WildcardQuery(new Term("subject","job*"));
            indexSearcher.search(query,prefixFilter,20);
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<div class="ibm-alternate-rule">
<hr />
</div>
<p class="ibm-ind-link ibm-back-to-top" sizset="114" sizcache="22"><a class="ibm-anchor-up-link" href="#ibm-pcon">回页首</a></p>
<p sizset="115" sizcache="22"><a name="N1042F"><span class="atitle">结束语</span></a></p>
<p>Lucene 是来自 Apache 的一个非常流行的开源搜索库, 它为应用程序提供了强大的索引编制和搜索功能。它提供了一个简单易用的 API，只需要稍微了解索引编制和搜索的原理即可使用。在本文中，您学习了 Lucene 架构及其核心 API。</p>
<p>Lucene 为许多知名网站和组织提供了各种强大的搜索功能。它还兼容许多其他编程语言。Lucene 有一个活跃的大型技术用户社区。如果您需要一些易用、可扩展以及高性能的开源搜索库，Apache Lucene 是一个极佳的选择。</p>
<!-- CMA ID: 428076 --><!-- Site ID: 10 --><!-- XSLT stylesheet used to transform this file:  dw-article-6.0-beta.xsl --><br />
http://www.ibm.com/developerworks/cn/opensource/os-apache-lucenesearch/
 <img src ="http://www.blogjava.net/freeman1984/aggbug/344555.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/freeman1984/" target="_blank">@joe</a> 2011-02-17 16:41 <a href="http://www.blogjava.net/freeman1984/archive/2011/02/17/344555.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>