lucene简介

本文是我们名为“ Apache Lucene基础知识 ”的学院课程的一部分。

在本课程中,您将了解Lucene。 您将了解为什么这样的库很重要,然后了解Lucene中搜索的工作方式。 此外,您将学习如何将Lucene Search集成到您自己的应用程序中,以提供强大的搜索功能。 在这里查看 !

目录

1.简介
1.1什么是全文搜索 1.2为什么我们需要全文搜索引擎 1.3 Lucene的工作方式 1.4基本Lucene工作流程
2.索引的基本组件
2.1目录 2.2文件 2.3。 领域 2.4。 条款 2.5。 分析仪 2.6与索引互动
3.搜索的基本组件
3.1 QueryBuilder和查询 3.2 IndexReader 3.3 IndexSearcher 3.4 TopDocs 3.5 ScoreDoc
4.一个简单的搜索应用程序
4.1使用Eclipse创建一个新的Maven项目 4.2 Maven依赖 4.3。 一个简单的索引器类 4.4。 一个简单的搜索器类 4.5下载源代码
5.最后的笔记

1.简介

在本课程中,我们将深入探讨Apache Lucene。 Lucene是一款功能丰富的开源全文搜索工具。 这意味着Lucene将帮助您实现针对您的应用程序需求量身定制的全文搜索引擎。 我们将处理Lucene的Java风格,但请记住,存在用于各种编程语言的API客户端。

1.1什么是全文搜索

用户通常需要检索与某些条件匹配的文档或来源列表。 例如,图书馆用户需要能够找到特定作者撰写的所有书籍。 或所有书名中带有特定单词或短语的书籍。 或在特定年份从特定出版商发行的所有书籍。 上面的查询可以通过众所周知的关系数据库轻松地处理。 如果您拥有一个存储元组, 标题,作者,出版者,出版年)元组的表,则可以有效地完成上述搜索。 现在,如果用户想要获取在其实际内容中包含某个单词或短语的所有文档,该怎么办? 如果您尝试使用传统数据库并将所有文档的原始内容存储在元组的字段中,那么搜索将花费不可接受的时间。

那是因为在全文搜索中 ,搜索引擎必须扫描文本文档或一般文本流中的所有单词 ,并尝试针对它匹配多个条件,例如查找其内容中的某些单词或短语。 传统的关系数据库中的此类查询将毫无希望。 当然,许多数据库系统(例如MySQL和PostgreSQL)都支持全文搜索,无论是本机搜索还是使用外部库。 但这效率不高,速度不够快或无法自定义。 但是最大的问题是可伸缩性。 他们只是无法处理全文搜索引擎可以处理的数据量。

1.2为什么我们需要全文搜索引擎

生成大量数据的过程是我们这个时代的主要特征之一,也是技术进步的主要结果。 它被称为信息过载 。 话虽如此,只有当您能够从中提取有用的信息,并使应用程序的最终用户可以访问这些信息时,收集和存储所有这些数据才有用。 当然,最著名和最常用的工具就是搜索。

有人可能会争辩说,在文件中搜索单词或短语就像从上到下以串行方式扫描文件一样简单,就像使用grep命令一样。 实际上,这可能只需要少量的文档。 但是,拥有数百万个文件的巨大文件系统又如何呢?如果这对您而言似乎非同寻常,那么网页,数据库,电子邮件,代码存储库,仅举几例,将它们全部结合在一起,又如何呢? 容易理解的是,每个用户所需的信息可能驻留在一个小小的文档中,位于大量不同信息资源的某个地方。 而且该文档的检索必须像呼吸一样容易。

现在可以看到为什么完全定制的基于搜索的应用程序越来越受到关注和吸引。 更重要的是,搜索已成为最终用户体验的一个重要方面,以至于对于现代Web应用程序(从简单的博客到Twitter或Facebook之类的大型平台,甚至是军用级应用程序)来说,没有搜索功能都是不可理解的。 这就是为什么大型供应商不想冒险将其搜索功能弄乱,并希望保持它们尽可能快而又简单的原因。 这导致需要将搜索从简单功能升级到完整平台。 具有强大,高效,必要的灵活性和定制性的平台。 而Apache Lucene提供了,这就是为什么在上述大多数应用程序中都使用它的原因。

1.3 Lucene的工作方式

因此,您一定想知道Lucene如何执行快速的全文本搜索。 毫不奇怪,答案是它使用了index 。 Lucene索引属于倒排索引的类别。 倒置索引不是在每个文档中都包含其包含的单词(或术语 )完整列表的经典索引,而是相反。 对于文档中的每个术语 (单词),您都有包含该术语的所有文档的列表。 当执行全文搜索时,这非常方便。

下图显示了反向索引如此之好的原因。 假设您有3个非常大的文件。 经典索引的格式如下:

经典索引:

 Document1 -> { going, to, dive, into, Apache, Lucene, rich, open , source , full, text, search,... }  Document2 -> { so, must, wonder, Lucene, can, achieve, very, fast, full, text, search, not,... }  Document3 -> { reason, that, inverted, index, work, good ,can, be, seen, following, diagrams,... } 

对于每个文档,都有一个包含所有术语的庞大列表。 为了查找文档是否包含特定术语,您必须进行扫描,可能是顺序扫描这些庞大的列表。

另一方面,反向索引将具有以下形式:

倒排索引:

 reason -> { (3,0} }  Lucene -> { (1,6), (2,4) }  full  -> { (1,10),(2,9) }  going -> { (1,0) }  index -> { (3,3) }  search -> { (1,11), (2,10)}  ... 

对于每个术语,我们维护一个包含该术语的所有文档的列表,然后是该术语在文档中的位置(当然,可以保留其他信息)。 现在,当用户搜索术语“ Lucene”时,我们可以立即回答,术语“ Lucene”位于文档1的位置6的位置和文档2的位置4的位置。总而言之,倒排索引使用大量可以立即搜索的小清单。 相反,经典索引将使用少量无法快速搜索的非常大的列表。

1.4基本Lucene工作流程

因此,Lucene必须在实际搜索之前完成一些工作。 大概就是创建索引。 索引过程的基本工作流程如下所示:

如上图所示:

  1. 您用文本文档/来源来喂它
  2. 对于每个文档,它都会分析文本并将其拆分为术语 (单词)。 同时,它可以在纯文本中执行各种分析。 您可以定制该步骤以适合您自己的应用程序的需求。
  3. 对于文档的每个术语,它都会创建先前描述的倒排列表。
  4. 现在可以开始搜索索引了。 您可以用许多不同的格式编写查询,结果将得到满足查询中指定条件的所有文档的列表。

到目前为止,Lucene似乎是一个非常强大的工具,因为它可以分析文本,创建索引并对该索引执行查询。 但是您必须自己做一些工作,例如选择要建立索引的文档,组织和管理整个过程以及过程的多个方面,以及最终从用户那里获得搜索查询并向他们提供任何可能的结果。

2.索引的基本组件

在本节中,我们将描述用于创建索引的基本组件和基本Lucene类。

2.1目录

Lucene索引仅托管在普通文件系统位置,或在需要额外性能且您不希望将其永久存储在驱动器上时存储在内存中。 您甚至可以选择通过JDBC将索引存储在数据库中。 前述选项的实现扩展了抽象Directory类。

为了简单起见,我们只说它使用了文件系统中的目录,尽管使用内存或数据库时并没有太多区别,但是我认为普通目录更加直观。 Lucene将使用该目录存储索引所需的所有内容。 您可以使用FSDirectory类使用这样的目录,并为它提供文件系统的任意路径(使用内存时,使用RAMDirectory )。 FSDirectory类只是普通Java File操作类之上的抽象。

这是创建FSDirectory

 Directory directory = FSDirectory.open( new File( "C:/Users/nikos/Index" )); 

这就是创建RAMDirectory

 Directory ramDirectory = new RAMDirectory(); 

2.2文件

如您所记得,我们说过,您有责任选择文档(文本文件,PDF,Word文档等)以及您要搜索的所有文本源,然后对其进行索引。 对于要索引的每个文档,必须创建一个代表该Document对象。 在这一点上,重要的是要了解文档是索引组件,而不是实际的文本源。 自然,由于Document代表单个物理文本源,因此它是索引的构建单元。 创建此类文档后,您必须将其添加到索引中。 稍后,在调度搜索时,结果将得到一个满足查询条件的Document对象的列表。

这样可以创建一个新的空Document

 Document doc = new Document(); 

现在是时候用Fields填充Document了。

2.3领域

Document对象填充有Fields的集合。 一个Field只是一对(名称,值)项。 因此,当创建一个新的Document对象时,必须用这种对来填充它。 Field可以存储在索引中,在这种情况下,字段的名称和值都按字面意义存储在索引中。 另外,可以对Field进行索引 ,或者更精确地说,可以对字段进行倒置 ,在这种情况下,该字段的值将被分析并标记为Terms ,并且可以进行搜索。 Term表示来自Field值文本的单词。 Field既可以被存储又可以被索引/取反 ,但是您不必存储一个字段就可以对其进行索引/取反。 存储字段和对字段建立索引/取反是两个不同的独立事物。

如前所述,在部署搜索时,作为回报,您将获得一个满足查询条件的Document对象列表(代表物理文本源)。 如果要访问Field的实际值,则必须声明该Field存储。 当您要存储本Document代表的文件名,上次修改日期,完整文件路径或有关您要访问的文本源的任何其他信息时,这通常很有用。 例如,如果您正在索引的文本源是电子邮件,则表示该电子邮件的Document对象可以具有以下字段:

代表电子邮件的示例文档:

领域

已储存

索引

名称

标题

来自示例的电子邮件

没有

位置

电子邮件位置

没有

example@javacodegeeks.com

没有

foo@example.com

没有

学科

通讯

没有

身体

嗨,您好 ! 很高兴见到你…

没有

在以上文档中,我选择了对电子邮件的正文进行索引/反转,但不进行存储。 这意味着将对电子邮件的正文进行分析并将其标记为可搜索的术语,但实际上不会将其存储在索引中。 当文本源的内容量很大并且要节省空间时,可以采用这种策略。 另一方面,我选择存储而不是索引所有其他字段。 当我执行搜索时,将搜索正文 ,而搜索中未考虑所有其他字段,因为它们没有被索引。

如果Body的上述切分项符合查询,这个Document将被包括在结果中。 现在,当您访问检索到的Document ,您只能查看其存储的Fields及其值。 因此,尽管可以搜索,但文件的实际主体将无法通过Document对象提供给您。 您只能看到标题,位置,从,到主题 Fields 。 存储该电子邮件的位置,将有助于我访问其实际正文内容。 当然,如果要通过Document对象检索电子邮件的主体,从而使其既可搜索又可存储(其他字段也是如此),则也可以存储电子邮件的主体。

因此,让我们看看如何创建上述Document 。 要创建仅存储的字段,我们将使用StoredField类。 为了创建文本的未存储和索引主体,我们将使用TextField类。

领域 

如您所见,我们给了FileReader作为"body"字段的值。 在分析阶段中将使用此FileReader ,以从该源中提取纯文本。 从文件中提取纯文本后,Lucene的特殊组件将对其进行分析并将其拆分为索引词。

2.4条款

术语表示文本中的单词。 术语是从Fields值的分析和标记化中提取的,因此Term是搜索的单位。 术语由两个元素组成,实际的文字单词(可以从文字到电子邮件地址,日期等的任何形式)以及该单词出现的字段的名称。

标记和分析字段以从中提取术语并不是绝对必要的。 在上一个示例中,如果要对“ From Field索引,则不必真正将其标记化。 电子邮件地址example@javacodegeeks.com可以用作Term

2.5分析仪

Analyzer是索引和搜索过程中最关键的组件之一。 它负责获取纯文本并将其转换为可搜索的术语。 现在,重要的是要了解分析器可以使用纯文本输入。 提供一个解析器以将文本源(例如HTML页面或文件系统中的文件)转换为纯文本,是程序员的责任。 该解析器通常是Reader。 例如,如果是文件,则可以是FileReader。

分析器内部使用Tokenizer 。 令牌生成器可以将上述阅读器用作输入,并使用它从特定来源(例如文件)中提取纯文本。 在获得纯文本之后,令牌生成器将文本简单地拆分为单词。 但是,分析器可以做的不仅仅是简单的文本拆分。 它可以执行多种文本和单词分析,例如:

  • 词干:用词干代替词。 例如,在英语中,“橙色”的词干是“橙色”。 因此,如果最终用户搜索“橙色”,则将获得包含“橙色”和“橙色”的文档。
  • 停用词过滤:执行搜索时,诸如“ the”,“ and”和“ a”之类的词没有特别的意义,因此不妨将其视为“噪音”。 删除它们将导致更好的性能和更准确的结果。
  • 文本规范化:删除重音符号和其他字符标记。
  • 同义词扩展:在与当前单词相同的标记位置添加同义词。

这些只是Lucenes Analyzer类内置的一些分析工具。 分析器中最常用的内置工具是StandardAnalyzer ,它可以删除停用词,将单词转换为小写字母并进行词干处理。 如您所知,不同的语言有不同的语法规则。 Lucene社区正在尝试为尽可能多的不同语言嵌入尽可能多的语法。 但是,如果Lucene的内置分析仪都不适合您的应用程序,则可以创建自己的分析仪。

2.6与索引互动

到目前为止,我们已经看到了如何创建索引Directory ,创建Document并向其添加Fields 。 现在,我们必须将Document写入Directory ,然后将其添加到索引。 这也是步骤,其中AnalyzersTokenizers发挥自己的部分。

正如您所期望的那样,在Lucene中没有称为Index (或类似的东西)的特殊类。 与索引进行交互的方式是通过IndexWriter ,当您要将内容推送到索引(并通常对其进行操作)时,通过IndexReader从索引中读取内容,以及通过IndexSearcher ,当您要搜索索引时课程。

现在,让我们看看如何创建所需的IndexWriter

领域 

我们选择为此使用StandardAnalyzer实例。 其构造函数将Version.LUCENE_46作为参数。 这有助于发现多个Lucene版本之间的兼容性依赖性。 请记住, StandardAnalyzer在内部使用StandardTokenizer 。 然后,我们创建一个IndexWriterConfig实例。 这是一个帮助程序类,可以保存IndexWriter所有配置选项。 如您所见,我们已指定我们希望IndexWriter使用先前创建的analyzer并将其设置为适当的版本。 最后,我们创建IndexWriter实例。 在其构造函数参数中,我们提供FSDirectory实例和先前创建的配置选项。

现在,您可以继续使用上述IndexWriter将先前创建的Document添加到Index中:

领域 

就是这样。 现在,当addDocument时,所有前面描述的操作都会发生:

  1. Tokenizer使用FileReader读取文件并将其转换为纯文本。 然后将其分解为令牌。
  2. 同时, Analyzer可以对纯文本然后对单个标记执行各种语法和语法分析。
  3. 通过令牌分析,将创建Terms并用于生成倒排索引。
  4. 最后,将包含Document和索引的所有信息的所有必需文件都写入指定的路径: "C:/Users/nikos/Index"

现在我们的文档已建立索引。 添加到索引的每个Document都遵循相同的过程。

现在,一切都变得更加清晰了,让我们来看一下在图表中使用的类的索引编制过程:

如你看到的:

  • 我们将Document对象传递给IndexWriter
  • 他使用AnalyzerReader获得的纯文本中生成Terms
  • 然后,他将更新索引所需的所有内容都写入Directory

尝试构建搜索引擎时,索引编制工作很难,因为您必须:

  • 选择您要索引的文档和文本源。
  • 提供读取器类,以读取文本源并将其转换为纯文本。 内置的类(或外部库)种类繁多,可以读取大量的文档格式。 但是,如果它们都不适合您的文档,则您将必须编写自己的Reader来解析它们并将其转换为纯文本。
  • 确定适合您应用程序需求的标记和分析策略。 大多数应用程序使用StandardAnalyzer和StandardTokenizer都可以正常工作。 但是,您可能想进一步自定义分析步骤,这需要做一些工作。
  • 确定使用哪种字段,以及存储和/或索引哪些字段。

3.搜索的基本组件

在本节中,我们将描述用于执行搜索的基本组件和基本Lucene类。 搜索是Lucene这样的平台的目标,因此它必须尽可能灵活和容易。

3.1 QueryBuilder和查询

在Lucene中,传递给Index的每个查询都是一个Query对象。 因此,在与索引进行实际交互以执行搜索之前,必须构建此类对象。

一切都以查询字符串开头。 就像您放在众所周知的搜索引擎(例如Google)上的查询字符串一样。 可以是任意短语,也可以是结构更复杂的短语,我们将在下一课中看到。 但是只发送要在索引中搜索的原始字符串将是没有用的。 您必须像处理带索引的纯文本一样处理它。 您必须将查询字符串拆分为单词并创建可搜索的术语。 据推测,这可以使用分析仪来完成。

注意:需要注意的重要一点是,您应该使用与用于索引过程的分析器相同的Analyzer子类来检查查询,以检查纯文本。

这是创建由StandardAnalyzer处理的简单查询的方式:

领域 

我们将QueryBuilder对象与StandarAnalyzer的实例绑定。 现在,您可以使用该QueryBuilder实例创建Query对象。

Query是一个抽象类,并且有许多具体的子类可用,例如:

  • 搜索包含特定术语的Document的TermQuery
  • 创建其他查询的布尔组合的BooleanQuery
  • WildcardQuery以实现通配符搜索,例如用于查询字符串“ * abc *”。
  • PhraseQuery可以搜索整个短语,而不仅仅是单个术语。
  • PrefixQuery搜索具有预定义前缀的术语。

所有这些不同的Query风格都将确定将在索引上执行的搜索的性质。 并且每个对象都可以通过该QueryBuilder实例获得。 在我们的示例中,我们选择使用createBooleanQuery方法。 它有两个参数。 第一个是将要搜索其值(确定为索引且可能已标记化)的Field的名称。 第二个是将使用StandardAnalyzer分析的查询字符串。 createBooleanQuery可以根据查询字符串的语法返回TermQueryBooleanQuery

3.2 IndexReader

大概是要在索引中进行搜索,首先必须打开它。 您可以使用IndexReader打开和访问它。 所有需要将数据从索引中拉出的过程都通过该抽象类。

使用IndexReader打开已经创建的索引非常容易:

领域 

如您所见,我们使用DirectoryReader打开存储索引的目录。 DirectoryReader返回索引的句柄,这就是IndexReader的含义。

3.3 IndexSearcher

IndexSearcher是用于搜索单个Index的类。 它与IndexReader绑定。

这是创建一个的方法:

领域 

您可以使用IndexSearcherQuery对象传递给IndexReader 。 方法如下:

领域 

我们使用IndexSearcher public TopDocs search(Query query, int n)方法执行搜索。 此方法需要两个参数。 第一个是Query对象。 第二个是整数,用于设置返回的搜索结果数的限制。 例如,如果您有10000个满足查询条件的文档,则可能不希望全部返回。 您可以声明只需要前n个结果。 最后,该方法返回一个TopDocs实例。

3.4 TopDocs

TopDocs类表示满足您的查询的匹配。 TopDocs有一个public ScoreDoc[]类字段。

3.5 ScoreDoc

SocreDoc代表查询命中。 它包括 :

  • 一个public int doc字段,即满足查询条件的Document的ID。
  • 还有一个public float score字段,即Document在查询中获得的分数。

评分公式是任何搜索平台中必不可少且非常复杂的部分,这正是Lucene发挥出色的作用。 该公式用于为检索到的文档提供相关性度量。 分数越高,Document与您的查询越相关。 这有助于表征“好”和“差”的文档,并确保为您提供尽可能接近您真正需要的文档的高质量结果。 您可以在当前版本的“ 相似性”类的文档, 旧版本的“ 相似性”类的文档中以及此信息检索文章中找到一些有关评分的有用信息。

4.一个简单的搜索应用程序

我们将构建一个简单的搜索应用程序,该应用程序将演示索引和搜索的基本步骤。 在此应用程序中,我们将使用包含一堆Java源文件的输入文件夹。 本文档中的每个文件都将被处理并添加到索引中。 然后,我们将对该索引执行简单查询,以了解其工作原理。

我们将使用:

  • Eclipse Kepler 4.3作为我们的IDE。
  • JDK 1.7。
  • Maven 3构建我们的项目。
  • Lucene 4.6.0,Lucene的最新版本。

首先,让我们使用Eclipse创建我们的Maven项目。

4.1使用Eclipse创建一个新的Maven项目

打开Eclipse并转到File-> New-> Other-> Maven-> Maven Project,然后单击Next。

在下一个窗口中,选择“创建简单项目(跳过原型选择)”选项,然后单击下一步:

在下一个窗口中,填写组ID和工件ID,如下图所示,然后单击“完成”:

将使用以下结构创建一个新的Maven项目:

4.2 Maven依赖

打开pom.xml并添加使用Lucene库所需的依赖项:

pom.xml:

领域 

如您所见,我们将导入提供所有核心类的lucene-core-4.6.0.jar ,以及提供所有文本分析所需的所有类的lucene-analyzers-common-4.6.0.jar包。

一个简单的索引器类

要创建此类,请转到Eclipse的Package Explorer。 在src/java/main创建一个名为com.javacodegeeks.enterprise.lucene.index的新包。 在新创建的包下,创建一个名为SimpleIndexer的新类。

让我们看一下该类的代码,该代码将进行索引编制:

SimpleIndexer.java:

领域 

在上述类中,我们指定了将文本文件放置在C:/Users/nikos/Desktop/LuceneFolders/LuceneHelloWorld/SourceFiles输入文件夹,还将要存储索引的文件夹放置在C:/Users/nikos/Desktop/LuceneFolders/LuceneHelloWorld/Index

index方法上,首先我们创建一个新的StandardAnalyzer实例和一个新的IndexWriter实例。 IndexeWriter将使用StrandardAnalyzer分析文本,并将索引存储在FSDirectory指向上述索引路径。

有趣的是在for循环上。 对于源目录中的每个文件:

  1. 我们创建一个新的Document实例。
  2. 我们添加了一个新的Filed ,确切地说是一个TextField ,它表示文件的内容。 请记住, TextField用于创建一个字段,该字段的值将被标记索引不存储
  3. 我们添加了另一个Field ,这次是一个StoredFiled ,其中包含文件名。 请记住, StoredField用于刚刚存储未建立索引未标记化的字段。 因为我们将文件名存储为完整路径,所以以后可以使用它来访问,显示和检查其内容。
  4. 然后,我们只需将Document添加到索引中即可。

循环后:

  1. 我们调用IndexWriter maxDoc()方法,该方法返回索引Documents的数量。
  2. 我们关闭IndexWriter ,因为我们不再需要它,因此系统可以回收其资源。

当我运行此代码时,这是它产生的输出

领域 

Here is the index folder in my system. As you can see, several special files are created (more on that next lessons):

Now let's search that index.

4.4。

To create this class go to the Package Explorer of Eclipse. Under src/java/main create a new package named com.javacodegeeks.enterprise.lucene.search . Under the newly created package, create a new class named SimpleSearcher .

To get a more clear view of he final structure of the project, have a look at the image bellow:

Let's see the code of that class, which will do the searching:

SimpleSearcher.java:

领域 

In the searchIndex method we pass the index directory and the query string as arguments. So I'm going to search for “private static final String”. Remember that the files I've indexed were Java source files,

The code is pretty self explanatory:

  1. We open the index directory and obtain the IndexReader and IndexSearcher classes.
  2. We then use the QueryBuilder , fed with the StrandardAnalyzer , to build our Query object. We used createBooleanQuery to obtain the Query object. Our query string does not have a boolean format (as we will see in the next lesson), so the method will create TermQueries for the analyzed and tokenized terms of the query string.
  3. We then use the search method of the IndexSearcher to perform the actual search.
  4. We obtain the ScoreDocs that satisfied the query from the TopDocs returned from the search method. For every ID in that ScoreDocs array, we obtain the corresponding Document from the IndexSearcher .
  5. From that Document , using get method, we obtain the name of the file, stored in the value of the “fileName” Field .
  6. We finally print the name of the file and the score it achieved.

Let's run the program and see what is the output :

领域 

It is important to understand that these files do not certainly contain the whole phrase "private static final String" . Intuitively, the documents with the higher score contain most of the words of that sentence and more frequently than documents with smaller scores. Of course the scoring formula is much more complex than that, as we said earlier.

For example if you change:

领域 

领域 

the whole phrase will be searched. Only documents that contain the whole phrase will be returned. When you run the code with that minor change, here is the output :

领域 

These files contain the whole query string "private static final String" in their contents.

4.5 Download the source code

You can download the Eclipse project of this example here: LuceneHelloWorld.zip

5. Final notes

It is important to mention that an IndexReader reads the “image” that the index has the moment he opens it. So, if your application is dealing with text sources that change over short periods of time, it is possible that you have to re-index those files at run time. But you want to be sure that the changes are reflected when you search the Index, while your application is still running and you have already opened an IndexReader (who now is outdated). In this case you have to obtain an updated IndexReader like this:

领域 

This will ensure that you get a new more updated IndexReader , but only if the index has changed. Furthermore, if you want to achieve fast, near real time searches ( eg for stream data) you can obtain your IndexReader like so:

领域 

For performance reasons, the IndexWriter doesn't flush the changes of the index immediately to the disk. It uses buffers instead, and persists the changes asynchronously. Opening an IndexReader like in the above snippet, gives him immediate access to the write buffers of the IndexWriter , and thus he has instant access to index updates.

Finally, it's worth mentioning that IndexWriter is thread safe, thus you can use the same instance in many threads to add Documents one particular index. The same goes for the IndexReader and IndexSearcher . Many threads can use the same instance of these classes to simultaneously read or search the same index.

翻译自: https://www.javacodegeeks.com/2015/09/introduction-to-lucene.html

lucene简介

lucene简介_Lucene简介相关推荐

  1. DriverManager 驱动管理器类简介 JDBC简介(三)

    驱动程序管理器是负责管理驱动程序的,驱动注册以后,会保存在DriverManager中的已注册列表中 后续的处理就可以对这个列表进行操作 简言之,驱动管理器,就是字面含义,主要负责就是管理 驱动 概述 ...

  2. 【Android 高性能音频】Oboe 函数库简介 ( Oboe 简介 | Oboe 特点 | Oboe 编译工具 | Oboe 相关文档 | Oboe 测试工具 )

    文章目录 一.Oboe 简介 二.Oboe 特点 三.Oboe 编译工具 四.Oboe 文档 五.Oboe 测试 一.Oboe 简介 Oboe 简介 : ① 函数库 : Oboe 是 C++ 函数库 ...

  3. 【Android 应用开发】Paint 图形组合 Xfermod 简介 ( 图形组合集合描述 | Xfermod 简介 | PorterDuff 简介 )

    文章目录 图形组合 集合描述 Xfermod 简介 PorterDuff 由来 Xfermod 合成模式分类 图形组合 集合描述 图形组合 集合描述 : 1.下面我们先描述两个集合 : ① 集合 A ...

  4. Data Source与数据库连接池简介 JDBC简介(八)

    DataSource是作为DriverManager的替代品而推出的,DataSource 对象是获取连接的首选方法. 起源 为何放弃DriverManager DriverManager负责管理驱动 ...

  5. Swagger 学习笔记 | Swagger 简介 | Springfox 简介 | Springfox 2.9.2 常用注解 | Spring Boot 整合 Swagger2 案例

    文章目录 一.Swagger 简介 二.Springfox 简介 三.Springfox2.9.2 常用注解 四.SpringBoot 整合 Swagger2 4.1 引入Maven依赖 4.2 项目 ...

  6. 【AOP 面向切面编程】AOP 简介 ( AspectJ 简介 | AspectJ 下载 )

    文章目录 一.AOP 简介 二.AspectJ 简介 三.AspectJ 下载 一.AOP 简介 AOP 是 Aspect Oriented Programming 的缩写 , 面向切面编程 ; 利用 ...

  7. 【Flutter】Flutter Gallery 官方示例简介 ( 项目简介 | 工程构建 )

    文章目录 一.Flutter Gallery 简介 二.Flutter Gallery 项目构建 发现一个很强的 Flutter 开源项目 , 由 Flutter 官方提供的 Flutter Gall ...

  8. 【Android 异步操作】AsyncTask 异步任务 ( 参数简介 | 方法简介 | 使用方法 | AsyncTask 源码分析 )

    文章目录 一.AsyncTask 参数简介 二.AsyncTask 方法简介 三.AsyncTask 基本用法 四.AsyncTask 构造函数源码解析 五.AsyncTask 构造函数相关源码注释 ...

  9. gan简介_GAN简介

    gan简介 目录: (TABLE OF CONTENTS:) INTRODUCTION介绍 HISTORY OF GANsGAN的历史 INTUITIVE EXPLANATION OF GANsGAN ...

最新文章

  1. 数组排序c语言函数_C语言如何写出返回数组最大最小值之差的函数(C primer plus 10-5)...
  2. ES2017异步函数现已正式可用
  3. 3 5的二维数组C语言程序,C语言及程序设计提高例程-33 二维数组元素的引用
  4. 纪中2016.10.6比赛不明总结
  5. 《复联4》首轮公映票房27.5亿美金 超《阿凡达》创纪录
  6. 爱奇艺漫威等系列电影因版权到期下架 会员无补偿
  7. 95-30-050-java.util-LinkedHashMap
  8. AJAX(Asynchronous JavaScript And XML,异步JavaScript + XML)
  9. 为导入的项目更改cvs用户名
  10. linux打开mid格式音乐,mid文件扩展名,mid文件怎么打开?
  11. python语义分析_NLPIR语义分析系统——文本分析利器
  12. 最简单!阿里云服务器采用 LNMP一键安装包 配置 Linux+Nginx+Mysql+PHP
  13. Python获取本机ip地址的两种有效方法
  14. 如何将EAN13码批量输出成PDF
  15. win ollvm环境_打造舒适搬砖环境,这些是我最想推介的桌面好物
  16. java xml 方法_Java读取xml的四种方式
  17. cv2 在图片上画线
  18. HAUT 1261 地狱飞龙
  19. stm32F407 连接 对射式红外对管 样例
  20. oracle 授权 解锁,给scott解锁和授权

热门文章

  1. Loj#2460-「POI2010」桥Bridges【网络流,欧拉回路】
  2. nssl1437-逮虾户【二分答案】
  3. P3870-[TJOI2009]开关【分块】
  4. P1967,ssl2267-货车运输【树上倍增LCA,最小生成树变形kruskal】
  5. ssl2342-打击犯罪【并查集】
  6. Wannafly挑战赛24
  7. JavaFX UI控件教程(四)之Button
  8. Spring零配置之@Configuration注解详解
  9. Maven Optional Exclusions使用区别
  10. 我们在进行着一场拔河比赛……