使用 Apache Lucene 搜索文本
2009-10-08 23:52
597 查看
本文将探讨 Apache Lucene —— 性能卓越、功能全面的文本搜索引擎库。我们将学习 Lucene 架构及其核心 API。学习如何使用 Lucene 进行跨平台全文本搜索、建立索引、显示结果,以及如何扩展搜索。
简介
Lucene
是一个开源、高度可扩展的搜索引擎库,可以从 Apache Software Foundation 获取。您可以将 Lucene
用于商业和开源应用程序。Lucene 强大的 API
主要关注文本索引和搜索。它可以用于为各种应用程序构建搜索功能,比如电子邮件客户端、邮件列表、Web
搜索、数据库搜索等等。Wikipedia、TheServerSide、jGuru 和 LinkedIn 等网站都使用了 Lucene。
Lucene 还为 Eclipse IDE、Nutch(著名的开源 Web 搜索引擎)以及 IBM®、AOL 和
Hewlett-Packard 等公司提供搜索功能。Lucene 已经兼容许多其他编程语言,包括 Perl、Python、C++ 和
.NET。到 2009 年 7 月 30 日止,用于 Java™ 编程语言的最新版 Lucene 为 V2.4.1。
Lucene 功能众多:
拥有强大、准确、有效的搜索算法。
计算每个文档匹配给定查询的分数,并根据分数返回最相关的文档。
支持许多强大的查询类型,比如 PhraseQuery、WildcardQuery、RangeQuery、FuzzyQuery、BooleanQuery 等。
支持解析人们输入的丰富查询表达式。
允许用户使用定制排序、过滤和查询表达式解析扩展搜索行为。
使用基于文件的锁定机制保护并发索引修改。
允许同时搜索和编制索引。
使用 Lucene 构建应用程序
如图 1 所示,使用 Lucene 构建功能全面的搜索应用程序主要涉及编制数据索引、搜索数据和显示搜索结果几个方面。
图 1. 使用 Lucene 构建应用程序的步骤
本文从使用 Lucene V2.4.1 和 Java 技术开发的样例应用程序中挑选了一些代码片段。示例应用程序为存储在属性文件中一组电子邮件文档编制索引,并展示了如何使用 Lucene 的查询 API 搜索索引。该示例还让您熟悉基本的索引操作。
为数据编制索引
Lucene 允许您为任何文本格式的数据编制索引。Lucene 可以用于几乎任何数据源以及从中提取的文本信息。您可以使用 Lucene
编制索引并搜索 HTML 文档、Microsoft® Word 文档、PDF
文件中存储的数据。编制数据索引的第一步是让数据变成一个简单的文本格式。您可以使用定制解析器和数据转换器实现这一点。
编制索引的过程
编制索引
是将文本数据转换为有利于快速搜索的格式。这类似于书本后面的索引:为您指出主题在书中出现的位置。
Lucene 将输入数据存储在名为逆序
索引的数据结构中, 该数据结构以索引文件集的形式存储在文件系统或内存中。大部分 Web 搜索引擎都使用逆序索引。它允许用户执行快速关键字查询,查找匹配给定查询的文档。在将文本数据添加到索引前,由分析程序(使用分析过程)进行处理。
分析
分析
是将文本数据转换为搜索基本单位(称为项(term)
)的过程。在分析过程中,文本数据将经历多项操作:提取单词、移除通用单词、忽略标点符号、将单词变为词根形式、将单词变成小写等等。分析过程发生在编制索引和查询解析之前。分析将文本数据转换为标记,这些标记将作为项添加到 Lucene 索引中。
Lucene 有多种内置分析程序,比如
SimpleAnalyzer、StandardAnalyzer、StopAnalyzer、SnowballAnalyzer
等。它们在标记文本和应用过滤器的方式上有所区别。因为分析在编制索引之前移除单词,它减少了索引的大小,但是不利用精确的查询过程。您可以使用
Lucene 提供的基本构建块创建定制分析程序,以自己的方式控制分析过程。表 1 展示了一些内置分析程序及其处理数据的方式。
表 1. Lucene 的内置分析程序
核心索引编制类
表示索引文件存储位置的抽象类。有两个常用的子类:
— 在实际文件系统中存储索引的
实现。该类对于大型索引非常有用。
— 在内存中存储所有索引的实现。该类适用于较小的索引,可以完整加载到内存中,在应用程序终止之后销毁。由于索引保存在内存中,所以速度相对较快。
正如上文所述,分析程序负责处理文本数据并将其转换为标记存储在索引中。在编制索引前,
接收用于标记数据的分析程序。要为文本编制索引,您应该使用适用于该文本语言的分析程序。
默认分析程序适用于英语。在 Lucene 沙盒中还有其他分析程序,包括用于中文、日文和韩文的分析程序。
该接口用来实现从索引目录中定制删除过时提交的策略。默认删除策略是
,该策略仅保留最近的提交,并在完成一些提交之后立即移除所有之前的提交。
创建或维护索引的类。它的构造函数接收布尔值,确定是否创建新索引,或者打开现有索引。它提供在索引中添加、删除和更新文档的方法。
对索引所做的更改最初缓存在内存中,并周期性转储到索引目录。
公开了几个控制如何在内存中缓存索引并写入磁盘的字段。对索引的更改对于
不可见,除非调用
的提交或关闭方法。
创建一个目录锁定文件,以通过同步索引更新保护索引不受破坏。
允许用户指定可选索引删除策略。
列表 1. 使用 Lucene
将数据添加到索引
将文本数据添加到索引涉及到两个类。
表示搜索中查询或检索的数据片。
类封装一个字段名称及其值。Lucene 提供了一些选项来指定字段是否需要编制索引或分析,以及值是否需要存储。这些选项可以在创建字段实例时传递。下表展示了
元数据选项的详细信息。
表 2.
元数据选项的详细信息
是一个字段集合。Lucene 也支持推进文档和字段,这在给某些索引数据赋予重要性时非常有用。给文本文件编制索引包括将文本数据封装在字段中、创建文档、填充字段,使用
向索引添加文档。
列表 2 展示向索引添加数据的示例。
列表 2. 向索引添加数据
搜索索引数据
搜索是在索引中查找单词并查找包含这些单词的文档的过程。使用 Lucene 的搜索 API 构建的搜索功能非常简单明了。本小节讨论 Lucene 搜索 API 的主要类。
Searcher
是一个抽象基类,包含各种超负荷搜索方法。
是一个常用的子类,允许在给定的目录中存储搜索索引。
方法返回一个根据计算分数排序的文档集合。Lucene 为每个匹配给定查询的文档计算分数。
是线程安全的;一个实例可以供多个线程并发使用。
Term
Term
是搜索的基本单位。它由两部分组成:单词文本和出现该文本的字段的名称。Term 对象也涉及索引编制,但是可以在 Lucene 内部创建。
Query 和子类
是一个用于查询的抽象基类。搜索指定单词或词组涉及到在项中包装它们,将项添加到查询对象,将查询对象传递到
的搜索方法。
Lucene 包含各种类型的具体查询实现,比如
TermQuery、BooleanQuery、PhraseQuery、PrefixQuery、RangeQuery、
MultiTermQuery、FilteredQuery、SpanQuery 等。以下部分讨论 Lucene 查询 API 的主查询类。
搜索索引最基本的查询类型。可以使用单个项构建
。项值应该区分大小写,但也并非全是如此。注意,传递的搜索项应该与文档分析得到的项一致,因为分析程序在构建索引之前对原文本执行许多操作。
例如,考虑电子邮件标题 “Job openings for Java
Professionals at Bangalore”。假设您使用
编制索引。现在如果我们使用
搜索 “Java”,它不会返回任何内容,因为本文本应该已经规范化,并通过
转成小写。如果搜索小写单词 “java”,它将返回所有标题字段中包含该单词的邮件。
列表 3. 使用
搜索
您可以使用
在某个范围内搜索。索引中的所有项都以字典顺序排列。Lucene 的
允许用户在某个范围内搜索项。该范围可以使用起始项和最终项(包含两端或不包含两端均可)指定。
列表 4. 在某个范围内搜索
您可以使用
通过前缀单词进行搜索,该方法用于构建一个查询,该查询查找包含以指定单词前缀开始的词汇的文档。
列表 5. 使用
搜索
您可以使用
组合任何数量的查询对象,构建强大的查询。它使用
和一个关联查询的子句,指示查询是应该发生、必须发生还是不得发生。在
中,子句的最大数量默认限制为 1,024。您可以调用
方法设置最大子句数。
列表 6. 使用
进行搜索
您可以使用
进行短语搜索。
匹配包含特定单词序列的文档。
使用索引中存储的项的位置信息。考虑匹配的项之间的距离称为 slop
。默认情况下,slop 的值为零,这可以通过调用
方法进行设置。
还支持多个项短语。
列表 7. 使用
进行搜索
实现通配符搜索查询,这允许您搜索 arch*(可以查找包含 architect、architecture 等)之类的单词。使用两个标准通配符:
表示零个以上
表示一个以上
如果使用以通配符查询开始的模式进行搜索,则可能会引起性能的降低,因为这需要查询索引中的所有项以查找匹配文档。
列表 8. 使用 WildcardQuery 进行搜索
您可以使用
搜索类似项,该类匹配类似于指定单词的单词。类似度测量基于 Levenshtein(编辑距离)算法进行。在列表 9 中,
用于查找与拼错的单词 “admnistrtor” 最接近的项,尽管这个错误单词没有索引。
列表 9. 使用
进行搜索
对于解析人工输入的查询字符非常有用。您可以使用它将用户输入的查询表达式解析为 Lucene 查询对象,这些对象可以传递到
的搜索方法。它可以解析丰富的查询表达式。
内部将人们输入的查询字符串转换为一个具体的查询子类。您需要使用反斜杠(
)将
、
等特殊字符进行转义。您可以使用运算符
、
和
构建文本布尔值查询。
列表 10.
搜索人工输入的查询表达式
显示搜索结果
返回一组对分级搜索结果(如匹配给定查询的文档)的引用。您可以使用
的搜索方法确定需要检索的最优先搜索结果数量。可以在此基础上构建定制分页。您可以添加定制 Web 应用程序或桌面应用程序来显示搜索结果。检索搜索结果涉及的主要类包括
和
。
搜索结果中包含一个指向文档的简单指针。这可以封装文档索引中文档的位置以及 Lucene 计算的分数。
封装搜索结果以及
的总数。
以下代码片段展示了如何检索搜索结果中包含的文档。
列表 11. 展示搜索结果
基本的索引操作
基本的索引操作包括移除和提升文档。
从索引中移除文档
应用程序常常需要使用最新的数据更新索引并移除较旧的数据。例如,在 Web 搜索引擎中,索引需要定期更新,因为总是需要添加新网页,移除不存在的网页。Lucene 提供了
接口允许您对索引执行这些操作。
是一个提供各种方法访问索引的抽象类。Lucene 内部引用文档时使用文档编号,该编号可以在向索引添加或从中移除文档时更改。文档编号用于访问索引中的文档。
不得用于更新目录中的索引,因为已经打开了
。
在打开时总是搜索索引的快照。对索引的任何更改都可以看到,直到再次打开
。使用 Lucene 重新打开它们的
可以看到最新的索引更新。
列表 12. 从索引中删除文档
提升文档和字段
有时您需要给某些索引数据更高的重要级别。您可以通过设置文档或字段的提升因子实现这一点。默认情况下,所有文档和字段的默认提升因子都是 1.0。
列表 13. 提升字段
扩展搜索
Lucene 提供一个称为排序
的高级功能。您可以根据指示文档在索引中相对位置的字段对搜索结果进行排序。用于排序的字段必须编制索引但不得标记。搜索字段中可以放入 4 种可能的项值:整数值、long 值、浮点值和字符串。
还可以通过索引顺序排序搜索结果。Lucene 通过降低相关度(比如默认的计算分数)对结果排序。排序的顺序是可以更改的。
列表 14. 排序搜索结果
Filtering
是限制搜索空间,只允许某个文档子集作为搜索范围的过程。您可以使用该功能实现对搜索结果进行再次搜索,或者在搜索结果上实现安全性。Lucene
带有各种内置的过滤器,比如
BooleanFilter、CachingWrapperFilter、ChainedFilter、DuplicateFilter、
PrefixFilter、QueryWrapperFilter、RangeFilter、RemoteCachingWrapperFilter、
SpanFilter 等。
可以传递到
的搜索方法,以过滤匹配筛选标准的筛选文档。
列表 15. 筛选搜索结果
结束语
Lucene 是来自 Apache 的一个非常流行的开源搜索库, 它为应用程序提供了强大的索引编制和搜索功能。它提供了一个简单易用的 API,只需要稍微了解索引编制和搜索的原理即可使用。在本文中,您学习了 Lucene 架构及其核心 API。
Lucene 为许多知名网站和组织提供了各种强大的搜索功能。它还兼容许多其他编程语言。Lucene 有一个活跃的大型技术用户社区。如果您需要一些易用、可扩展以及高性能的开源搜索库,Apache
Lucene 是一个极佳的选择。
* 本文来自网络,仅用于学习与交流
http://www.ibm.com/developerworks/cn/opensource/os-apache-lucenesearch/index.html#main
简介
Lucene
是一个开源、高度可扩展的搜索引擎库,可以从 Apache Software Foundation 获取。您可以将 Lucene
用于商业和开源应用程序。Lucene 强大的 API
主要关注文本索引和搜索。它可以用于为各种应用程序构建搜索功能,比如电子邮件客户端、邮件列表、Web
搜索、数据库搜索等等。Wikipedia、TheServerSide、jGuru 和 LinkedIn 等网站都使用了 Lucene。
Lucene 还为 Eclipse IDE、Nutch(著名的开源 Web 搜索引擎)以及 IBM®、AOL 和
Hewlett-Packard 等公司提供搜索功能。Lucene 已经兼容许多其他编程语言,包括 Perl、Python、C++ 和
.NET。到 2009 年 7 月 30 日止,用于 Java™ 编程语言的最新版 Lucene 为 V2.4.1。
Lucene 功能众多:
拥有强大、准确、有效的搜索算法。
计算每个文档匹配给定查询的分数,并根据分数返回最相关的文档。
支持许多强大的查询类型,比如 PhraseQuery、WildcardQuery、RangeQuery、FuzzyQuery、BooleanQuery 等。
支持解析人们输入的丰富查询表达式。
允许用户使用定制排序、过滤和查询表达式解析扩展搜索行为。
使用基于文件的锁定机制保护并发索引修改。
允许同时搜索和编制索引。
|
使用 Lucene 构建应用程序
如图 1 所示,使用 Lucene 构建功能全面的搜索应用程序主要涉及编制数据索引、搜索数据和显示搜索结果几个方面。
图 1. 使用 Lucene 构建应用程序的步骤
本文从使用 Lucene V2.4.1 和 Java 技术开发的样例应用程序中挑选了一些代码片段。示例应用程序为存储在属性文件中一组电子邮件文档编制索引,并展示了如何使用 Lucene 的查询 API 搜索索引。该示例还让您熟悉基本的索引操作。
|
为数据编制索引
Lucene 允许您为任何文本格式的数据编制索引。Lucene 可以用于几乎任何数据源以及从中提取的文本信息。您可以使用 Lucene
编制索引并搜索 HTML 文档、Microsoft® Word 文档、PDF
文件中存储的数据。编制数据索引的第一步是让数据变成一个简单的文本格式。您可以使用定制解析器和数据转换器实现这一点。
编制索引的过程
编制索引
是将文本数据转换为有利于快速搜索的格式。这类似于书本后面的索引:为您指出主题在书中出现的位置。
Lucene 将输入数据存储在名为逆序
索引的数据结构中, 该数据结构以索引文件集的形式存储在文件系统或内存中。大部分 Web 搜索引擎都使用逆序索引。它允许用户执行快速关键字查询,查找匹配给定查询的文档。在将文本数据添加到索引前,由分析程序(使用分析过程)进行处理。
分析
分析
是将文本数据转换为搜索基本单位(称为项(term)
)的过程。在分析过程中,文本数据将经历多项操作:提取单词、移除通用单词、忽略标点符号、将单词变为词根形式、将单词变成小写等等。分析过程发生在编制索引和查询解析之前。分析将文本数据转换为标记,这些标记将作为项添加到 Lucene 索引中。
Lucene 有多种内置分析程序,比如
SimpleAnalyzer、StandardAnalyzer、StopAnalyzer、SnowballAnalyzer
等。它们在标记文本和应用过滤器的方式上有所区别。因为分析在编制索引之前移除单词,它减少了索引的大小,但是不利用精确的查询过程。您可以使用
Lucene 提供的基本构建块创建定制分析程序,以自己的方式控制分析过程。表 1 展示了一些内置分析程序及其处理数据的方式。
表 1. Lucene 的内置分析程序
分析程序 | 对文本数据的操作 |
---|---|
WhitespaceAnalyzer | 分解空白处的标记 |
SimpleAnalyzer | 分解非字母字符的文本,并将文本转为小写形式 |
StopAnalyzer | 移除虚字(stop word)—— 对检索无用的字,并将文本转为小写形式 |
StandardAnalyzer | 根据一种复杂语法(识别电子邮件地址、缩写、中文、日文、韩文字符、字母数字等等)标记文本 将文本转为小写形式 移除虚字 |
Directory
表示索引文件存储位置的抽象类。有两个常用的子类:
FSDirectory
— 在实际文件系统中存储索引的
Directory
实现。该类对于大型索引非常有用。
RAMDirectory
— 在内存中存储所有索引的实现。该类适用于较小的索引,可以完整加载到内存中,在应用程序终止之后销毁。由于索引保存在内存中,所以速度相对较快。
Analyzer
正如上文所述,分析程序负责处理文本数据并将其转换为标记存储在索引中。在编制索引前,
IndexWriter
接收用于标记数据的分析程序。要为文本编制索引,您应该使用适用于该文本语言的分析程序。
默认分析程序适用于英语。在 Lucene 沙盒中还有其他分析程序,包括用于中文、日文和韩文的分析程序。
IndexDeletionPolicy
该接口用来实现从索引目录中定制删除过时提交的策略。默认删除策略是
KeepOnlyLastCommitDeletionPolicy
,该策略仅保留最近的提交,并在完成一些提交之后立即移除所有之前的提交。
IndexWriter
创建或维护索引的类。它的构造函数接收布尔值,确定是否创建新索引,或者打开现有索引。它提供在索引中添加、删除和更新文档的方法。
对索引所做的更改最初缓存在内存中,并周期性转储到索引目录。
IndexWriter
公开了几个控制如何在内存中缓存索引并写入磁盘的字段。对索引的更改对于
IndexReader
不可见,除非调用
IndexWriter
的提交或关闭方法。
IndexWriter
创建一个目录锁定文件,以通过同步索引更新保护索引不受破坏。
IndexWriter
允许用户指定可选索引删除策略。
列表 1. 使用 Lucene
IndexWriter
//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); |
将文本数据添加到索引涉及到两个类。
Field
表示搜索中查询或检索的数据片。
Field
类封装一个字段名称及其值。Lucene 提供了一些选项来指定字段是否需要编制索引或分析,以及值是否需要存储。这些选项可以在创建字段实例时传递。下表展示了
Field
元数据选项的详细信息。
表 2.
Field
元数据选项的详细信息
选项 | 描述 |
---|---|
Field.Store.Yes | 用于存储字段值。适用于显示搜索结果的字段 — 例如,文件路径和 URL。 |
Field.Store.No | 没有存储字段值 — 例如,电子邮件消息正文。 |
Field.Index.No | 适用于未搜索的字段 — 仅用于存储字段,比如文件路径。 |
Field.Index.ANALYZED | 用于字段索引和分析 — 例如,电子邮件消息正文和标题。 |
Field.Index.NOT_ANALYZED | 用于编制索引但不分析的字段。它在整体中保留字段的原值 — 例如,日期和个人名称。 |
Document
是一个字段集合。Lucene 也支持推进文档和字段,这在给某些索引数据赋予重要性时非常有用。给文本文件编制索引包括将文本数据封装在字段中、创建文档、填充字段,使用
IndexWriter
向索引添加文档。
列表 2 展示向索引添加数据的示例。
列表 2. 向索引添加数据
/*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); |
|
搜索索引数据
搜索是在索引中查找单词并查找包含这些单词的文档的过程。使用 Lucene 的搜索 API 构建的搜索功能非常简单明了。本小节讨论 Lucene 搜索 API 的主要类。
Searcher
Searcher
是一个抽象基类,包含各种超负荷搜索方法。
IndexSearcher
是一个常用的子类,允许在给定的目录中存储搜索索引。
Search
方法返回一个根据计算分数排序的文档集合。Lucene 为每个匹配给定查询的文档计算分数。
IndexSearcher
是线程安全的;一个实例可以供多个线程并发使用。
Term
Term
是搜索的基本单位。它由两部分组成:单词文本和出现该文本的字段的名称。Term 对象也涉及索引编制,但是可以在 Lucene 内部创建。
Query 和子类
Query
是一个用于查询的抽象基类。搜索指定单词或词组涉及到在项中包装它们,将项添加到查询对象,将查询对象传递到
IndexSearcher
的搜索方法。
Lucene 包含各种类型的具体查询实现,比如
TermQuery、BooleanQuery、PhraseQuery、PrefixQuery、RangeQuery、
MultiTermQuery、FilteredQuery、SpanQuery 等。以下部分讨论 Lucene 查询 API 的主查询类。
TermQuery
搜索索引最基本的查询类型。可以使用单个项构建
TermQuery
。项值应该区分大小写,但也并非全是如此。注意,传递的搜索项应该与文档分析得到的项一致,因为分析程序在构建索引之前对原文本执行许多操作。
例如,考虑电子邮件标题 “Job openings for Java
Professionals at Bangalore”。假设您使用
StandardAnalyzer
编制索引。现在如果我们使用
TermQuery
搜索 “Java”,它不会返回任何内容,因为本文本应该已经规范化,并通过
StandardAnalyzer
转成小写。如果搜索小写单词 “java”,它将返回所有标题字段中包含该单词的邮件。
列表 3. 使用
TermQuery
搜索
//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); |
RangeQuery
您可以使用
RangeQuery
在某个范围内搜索。索引中的所有项都以字典顺序排列。Lucene 的
RangeQuery
允许用户在某个范围内搜索项。该范围可以使用起始项和最终项(包含两端或不包含两端均可)指定。
列表 4. 在某个范围内搜索
/* 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); |
PrefixQuery
您可以使用
PrefixQuery
通过前缀单词进行搜索,该方法用于构建一个查询,该查询查找包含以指定单词前缀开始的词汇的文档。
列表 5. 使用
PrefixQuery
搜索
//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")); |
BooleanQuery
您可以使用
BooleanQuery
组合任何数量的查询对象,构建强大的查询。它使用
query
和一个关联查询的子句,指示查询是应该发生、必须发生还是不得发生。在
BooleanQuery
中,子句的最大数量默认限制为 1,024。您可以调用
setMaxClauseCount
方法设置最大子句数。
列表 6. 使用
BooleanQuery
进行搜索
// 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); |
PhraseQuery
您可以使用
PhraseQuery
进行短语搜索。
PhraseQuery
匹配包含特定单词序列的文档。
PhraseQuery
使用索引中存储的项的位置信息。考虑匹配的项之间的距离称为 slop
。默认情况下,slop 的值为零,这可以通过调用
setSlop
方法进行设置。
PhraseQuery
还支持多个项短语。
列表 7. 使用
PhraseQuery
进行搜索
/* 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")); |
WildcardQuery
WildcardQuery
实现通配符搜索查询,这允许您搜索 arch*(可以查找包含 architect、architecture 等)之类的单词。使用两个标准通配符:
*
表示零个以上
?
表示一个以上
如果使用以通配符查询开始的模式进行搜索,则可能会引起性能的降低,因为这需要查询索引中的所有项以查找匹配文档。
列表 8. 使用 WildcardQuery 进行搜索
//Search for 'arch*' to find e-mail messages that have word 'architect' in the subject field./ Query query = new WildcardQuery(new Term("subject","arch*")); |
FuzzyQuery
您可以使用
FuzzyQuery
搜索类似项,该类匹配类似于指定单词的单词。类似度测量基于 Levenshtein(编辑距离)算法进行。在列表 9 中,
FuzzyQuery
用于查找与拼错的单词 “admnistrtor” 最接近的项,尽管这个错误单词没有索引。
列表 9. 使用
FuzzyQuery
进行搜索
/* 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")); |
QueryParser
QueryParser
对于解析人工输入的查询字符非常有用。您可以使用它将用户输入的查询表达式解析为 Lucene 查询对象,这些对象可以传递到
IndexSearcher
的搜索方法。它可以解析丰富的查询表达式。
QueryParser
内部将人们输入的查询字符串转换为一个具体的查询子类。您需要使用反斜杠(
/
)将
*
、
?
等特殊字符进行转义。您可以使用运算符
AND
、
OR
和
NOT
构建文本布尔值查询。
列表 10.
搜索人工输入的查询表达式
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"); |
|
显示搜索结果
IndexSearcher
返回一组对分级搜索结果(如匹配给定查询的文档)的引用。您可以使用
IndexSearcher
的搜索方法确定需要检索的最优先搜索结果数量。可以在此基础上构建定制分页。您可以添加定制 Web 应用程序或桌面应用程序来显示搜索结果。检索搜索结果涉及的主要类包括
ScoreDoc
和
TopDocs
。
ScoreDoc
搜索结果中包含一个指向文档的简单指针。这可以封装文档索引中文档的位置以及 Lucene 计算的分数。
TopDocs
封装搜索结果以及
ScoreDoc
的总数。
以下代码片段展示了如何检索搜索结果中包含的文档。
列表 11. 展示搜索结果
/* 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()); } |
基本的索引操作
基本的索引操作包括移除和提升文档。
从索引中移除文档
应用程序常常需要使用最新的数据更新索引并移除较旧的数据。例如,在 Web 搜索引擎中,索引需要定期更新,因为总是需要添加新网页,移除不存在的网页。Lucene 提供了
IndexReader
接口允许您对索引执行这些操作。
IndexReader
是一个提供各种方法访问索引的抽象类。Lucene 内部引用文档时使用文档编号,该编号可以在向索引添加或从中移除文档时更改。文档编号用于访问索引中的文档。
IndexReader
不得用于更新目录中的索引,因为已经打开了
IndexWriter
。
IndexReader
在打开时总是搜索索引的快照。对索引的任何更改都可以看到,直到再次打开
IndexReader
。使用 Lucene 重新打开它们的
IndexReader
可以看到最新的索引更新。
列表 12. 从索引中删除文档
// 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(); |
提升文档和字段
有时您需要给某些索引数据更高的重要级别。您可以通过设置文档或字段的提升因子实现这一点。默认情况下,所有文档和字段的默认提升因子都是 1.0。
列表 13. 提升字段
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); } |
|
扩展搜索
Lucene 提供一个称为排序
的高级功能。您可以根据指示文档在索引中相对位置的字段对搜索结果进行排序。用于排序的字段必须编制索引但不得标记。搜索字段中可以放入 4 种可能的项值:整数值、long 值、浮点值和字符串。
还可以通过索引顺序排序搜索结果。Lucene 通过降低相关度(比如默认的计算分数)对结果排序。排序的顺序是可以更改的。
列表 14. 排序搜索结果
/* 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); |
Filtering
是限制搜索空间,只允许某个文档子集作为搜索范围的过程。您可以使用该功能实现对搜索结果进行再次搜索,或者在搜索结果上实现安全性。Lucene
带有各种内置的过滤器,比如
BooleanFilter、CachingWrapperFilter、ChainedFilter、DuplicateFilter、
PrefixFilter、QueryWrapperFilter、RangeFilter、RemoteCachingWrapperFilter、
SpanFilter 等。
Filter
可以传递到
IndexSearcher
的搜索方法,以过滤匹配筛选标准的筛选文档。
列表 15. 筛选搜索结果
/*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); |
|
结束语
Lucene 是来自 Apache 的一个非常流行的开源搜索库, 它为应用程序提供了强大的索引编制和搜索功能。它提供了一个简单易用的 API,只需要稍微了解索引编制和搜索的原理即可使用。在本文中,您学习了 Lucene 架构及其核心 API。
Lucene 为许多知名网站和组织提供了各种强大的搜索功能。它还兼容许多其他编程语言。Lucene 有一个活跃的大型技术用户社区。如果您需要一些易用、可扩展以及高性能的开源搜索库,Apache
Lucene 是一个极佳的选择。
* 本文来自网络,仅用于学习与交流
http://www.ibm.com/developerworks/cn/opensource/os-apache-lucenesearch/index.html#main
相关文章推荐
- 使用 Apache Lucene 和 Solr 进行位置感知搜索——通过合并非结构化文本和空间数据改进搜索应用程序
- 使用 Apache Lucene 搜索文本
- 使用 Apache Lucene 搜索文本——轻松为应用程序构建搜索和索引功能
- 使用 Apache Lucene 搜索文本
- 使用 Apache Lucene 搜索文本
- 使用 Apache Lucene 搜索文本
- 使用 Apache Lucene 搜索文本
- 使用 Apache Lucene 和 Solr 进行位置感知搜索
- 使用 Apache Lucene 和 Solr 进行位置感知搜索
- 使用 Apache Lucene 和 Solr 4 实现下一代搜索和分析
- 使用 Apache Lucene 和 Solr 进行位置感知搜索
- 使用 Apache Lucene 和 Solr 4 实现下一代搜索和分析
- 使用 Apache Lucene 和 Solr 进行位置感知搜索
- 使用 Apache Lucene 和 Solr 进行位置感知搜索
- 使用 Apache Lucene 和 Solr 4 实现下一代搜索和分析
- 使用 Apache Lucene 和 Solr 进行位置感知搜索
- 使用Lucene+Paoding构建SSH2系统的站内搜索---
- Lucene4.10使用教程(十一):Lucene的近实时搜索
- 使用Lucene2.3构建搜索引
- Lucene使用Filter搜索过滤