lucene 增加相关性
许多用户不喜欢Lucene API的事务性语义,以及这在搜索应用程序中如何有用。 首先,Lucene实现了ACID属性:
- 一个 tomicity:当您在更改(添加,删除文件)
IndexWriter
会话,然后提交,要么全部(如果提交成功)或无的更改(如果提交失败)将是可见的,从来没有的东西在两者之间。 某些方法具有其自己的原子行为:如果调用updateDocument
,该方法实现为删除操作,然后执行添加操作,即使打开近实时(NRT)阅读器或从单独的线程提交。 同样,如果使用相对较新的addDocuments
方法添加文档块,则在获得的任何阅读器中都不会看到任何文档或全部文档。 - Çonsistency:如果计算机或操作系统崩溃,或JVM崩溃或被杀,或断电,你的指数将保持不变(即,未破坏)。 请注意,其他问题(例如RAM损坏,CPU翻转或文件系统损坏)仍然很容易损坏索引!
- 我这样想 :在
IndexWriter
进行更改时,任何对搜索索引的IndexReader
都不可见,直到您提交或打开新的NRT阅读器。 一次仅一个IndexWriter
实例可以更改索引。 - d urability:一旦
commit
的回报,所有的改变都被写入持久性存储器(假设你的I / O系统正确实现fsync
)。 如果计算机或操作系统崩溃,或者JVM崩溃或被杀死,或者计算机断电,则所有更改仍将存在于索引中。
Lucene提供了两阶段的提交 API:调用prepareCommit
方法来完成所有艰苦的工作(应用缓冲的删除,编写缓冲的文档,fsync文件)。 如果出现问题(例如磁盘已满),几乎肯定会在第一阶段发生。 然后,调用commit
完成事务。
当您关闭IndexWriter
,它commit
在IndexWriter
调用commit
。 相反,如果您想放弃自上一次提交以来的所有更改,请改为调用rollback
方法,该方法也将关闭编写器。 您甚至可以回滚CREATE
:如果您已有索引,并使用OpenMode.CREATE
在其上打开IndexWriter
,然后回滚,则索引将保持不变。 同样,如果调用deleteAll
然后回滚。
注意,仅在新目录上打开IndexWriter
并不会创建空提交。 也就是说,您必须先调用commit
才能在目录上打开IndexReader
。
Lucene本身并没有实现事务日志 ,但是很容易在顶层构建该层。 例如,流行的搜索服务器(例如Solr和ElasticSearch )就是这样做的。
在一个索引中多次提交
一个Lucene索引可以自由包含多个提交; 这是一个功能强大但经常被忽略的功能。 每个提交都拥有创建提交时所存在的索引的时间点视图。
这类似于ZFS和即将出现的Btrfs等现代文件系统中可用的快照和可写克隆。 实际上,Lucene能够基于相同的根本原因有效地公开多个提交:所有索引段和文件都是一次写入的,就像ZFS和Btrfs中的文件块一样。
要在索引中保存多个提交,只需实现自己的IndexDeletionPolicy
并将其传递给IndexWriter
。 这是Lucene用来了解应删除哪些提交的类: IndexWriter
在打开索引时以及每次提交成功时都会调用它。 默认策略KeepOnlyLastCommitDeletionPolicy
删除除最后一次提交以外的所有内容。 如果您使用NoDeletionPolicy
则将保留每个提交!
您可以将userData
( Map
)传递给commit
,以记录有关该提交的自定义信息(对Lucene不透明),然后使用IndexReader.listCommits
在索引中查找所有提交。 找到提交后,您可以在其上打开IndexReader
来搜索该提交时的索引。
您还可以在先前的提交上打开IndexWriter
,以有效地回滚之后的所有更改:这与rollback
方法类似,不同之处在于,它使您可以跨提交进行回滚,而不仅仅是在当前IndexWriter
会话中进行的更改。
即使使用OpenMode.CREATE
打开索引,旧提交仍将保留。 当IndexReader
仍在搜索旧提交时,传递OpenMode.CREATE
也可以。 这可以实现有趣的用例,例如在每次提交之间完全重新索引您的内容,而不会影响任何开放的读者。
结合所有这些有趣的事务功能,您可以做一些很酷的事情:
- 使用
SnapshotDeletionPolicy
或PersistentSnapshotDeletionPolicy
热备份 :这些删除策略使“实时”备份索引变得很简单,而不会阻止使用IndexWriter
进行的更改。 备份可以很容易地进行增量备份(只需复制新文件,删除已删除的文件),就可以自由限制IO以最大程度地减少对搜索的干扰。 - 搜索不同的目录版本:也许您运行了一个电子商务网站,但是却发布了多个版本的目录。 在这种情况下,您可以保留较旧的提交,每次提交都搜索目录的特定版本,从而使用户可以选择要搜索的目录。
- 来自相同初始索引的可重复索引测试:也许您想运行一堆性能测试,也许从一个大的初始索引开始尝试不同的RAM缓冲区大小或合并因子。 为此,只需运行每个测试,但是最后,不要关闭
IndexWriter
,而使用rollback
方法将索引快速返回其初始状态,以准备进行下一个测试。 - 强制将所有索引段合并到单个段,但同时保留先前的多段提交。 然后,您可以进行测试以比较多段性能与单段性能。
- 索引和搜索NFS文件系统 :因为NFS不能保护仍处于打开状态的文件不被删除,所以必须使用
IndexDeletionPolicy
保留每个提交,直到所有打开的阅读器都完成了提交(即,重新打开为新的提交)。 简单的方法是基于时间的,例如:不要删除提交,直到提交时间为15分钟,然后始终每5分钟重新打开阅读器一次。 没有这个,在NFS上搜索时,您将遇到各种可怕的异常。 - 分布式提交:如果您还有其他资源必须随原子对Lucene索引的更改一起提交,则可以使用两阶段提交API。 这很简单,但是很容易在第二阶段失败。 为了从这种情况下恢复过来,例如,如果Lucene完成了其第二阶段的提交,但是数据库的第二阶段遇到了一些错误,崩溃或断电,则可以通过在先前的提交上打开
IndexWriter
轻松回滚Lucene的提交。 - 实验性的索引更改:也许您想尝试以新的方式重新索引索引的某些子集,但是您不确定它是否会成功。 在这种情况下,只需保留旧的提交,然后在未解决的情况下回滚,或者如果删除则删除旧的提交。
- 基于时间的快照:也许您希望自由地回滚到1天,1周前,1个月前等的索引,因此您可以根据提交的时间来保留提交。
请记住,保持多个提交活动必定会占用额外的磁盘空间,但是,开销通常很小,因为多个提交通常会共享公共段,尤其是较大的旧段。
翻译自: https://www.javacodegeeks.com/2013/06/transactional-lucene.html
lucene 增加相关性