7.8. 高级功能


7.8.1. 访问 SearchFactory

SearchFactory 对象跟踪 Hibernate Search 的底层 Lucene 资源。它是原生访问 Lucene 的便捷方式。SearchFactory 可以从 FullTextSession 访问:

示例:访问 SearchFactory

FullTextSession fullTextSession = Search.getFullTextSession(regularSession);
SearchFactory searchFactory = fullTextSession.getSearchFactory();
Copy to Clipboard Toggle word wrap

7.8.2. 使用 IndexReader

Lucene 中的查询在 IndexReader 上执行。Hibernate 搜索可能会缓存索引读取器以最大化性能,或者提供其他有效策略来检索更新的 indexReader 最小化 I/O 操作。您的代码可以访问这些缓存的资源,但有几个要求。

示例:访问 IndexReader

IndexReader reader = searchFactory.getIndexReaderAccessor().open(Order.class);
try {
   //perform read-only operations on the reader
}
finally {
   searchFactory.getIndexReaderAccessor().close(reader);
}
Copy to Clipboard Toggle word wrap

在本例中,SearchFactory 确定查询此实体需要哪些索引(包含分片策略)。使用每个索引上配置的 ReaderProvider,它会在所有涉及的索引之上返回复合 IndexReader。因为这个 IndexReader 在多个客户端间共享,所以您必须遵循以下规则:

  • 从不调用 indexReader.close(),而是在需要时使用 readerProvider.closeReader(reader),最好是在最后的块中。
  • 不要使用此 IndexReader 进行修改操作(它是只读 indexReader,任何这种尝试都将导致异常)。

除了这些规则外,您还可以自由使用 IndexReader,特别是执行原生 Lucene 查询。使用共享 IndexReaders 时,与从文件系统直接打开一个查询相比,将提高大多数查询的效率。

作为方法 open(Class…​ type)的替代方案,您可以使用 open(String…​ indexNames),允许您传递一个或多个索引名称。如果使用分片,您还可以使用此策略为任何索引类型选择索引子集。

示例:按索引名称访问 IndexReader

IndexReader reader = searchFactory.getIndexReaderAccessor().open("Products.1", "Products.3");
Copy to Clipboard Toggle word wrap

7.8.3. 访问 Lucene 目录

目录是 Lucene 用来表示索引存储的最常见抽象;Hibernate Search 不会直接与 Lucene Directory 交互,而是通过索引管理器提取这些交互:索引不一定需要由目录实施。

如果您知道您的索引是表示为目录且需要访问它,您可以通过 IndexManager 获得对目录的引用。将 IndexManager 转换为 DirectoryBasedIndexManager,然后使用 getDirectoryProvider().getDirectory() 来获取对底层目录的引用。不建议您这样做,我们鼓励改为使用 IndexReader。

7.8.4. sharding Indexes

在某些情况下,将给定实体的索引化数据分到几个 Lucene 索引中非常有用。

警告

只有在优点大于缺点时才应实施分片。搜索分片索引通常较慢,因为所有分片都必须打开一次搜索。

分片的可能用例是:

  • 单个索引非常大,因此索引更新时间正在减慢应用程序的速度。
  • 典型的搜索只会达到索引的一个子集,例如数据自然被客户、区域或应用细分。

默认情况下不启用分片,除非配置了分片数量。要做到这一点,请使用 hibernate.search.<indexName>.sharding_strategy.nbr_of_shards 属性。

示例:启用索引划分

在本例中,启用五个分片。

hibernate.search.<indexName>.sharding_strategy.nbr_of_shards = 5
Copy to Clipboard Toggle word wrap

负责将数据拆分为 sub-indexes 是 indexShardingStrategy。默认分片策略会根据 ID 字符串表示法的散列值(由 FieldBridge 生成)来分割数据。这可确保比较平衡的分片。您可以通过实施自定义 IndexShardingStrategy 来替换默认策略。要使用自定义策略,您必须设置 hibernate.search.<indexName>.sharding_strategy 属性。

示例:指定自定义划分策略

hibernate.search.<indexName>.sharding_strategy = my.shardingstrategy.Implementation
Copy to Clipboard Toggle word wrap

IndexShardingStrategy 属性还允许通过选择针对哪个分片运行查询来优化搜索。通过激活过滤器,分片策略可以选择用于应答查询的分片的子集(IndexShardingStrategy.getIndexManagersForQuery),从而加快查询执行。

每个分片都有独立的 IndexManager,因此可以配置为使用不同的目录供应商和后端配置。以下示例中 Animal 实体的 IndexManager 索引名称是 Animal.0 到 Animal.4。换句话说,每个分片都有其自己的索引的名称,后跟 . (dot)及其索引号。

示例:对实体 Animal 进行划分配置

hibernate.search.default.indexBase = /usr/lucene/indexes
hibernate.search.Animal.sharding_strategy.nbr_of_shards = 5
hibernate.search.Animal.directory_provider = filesystem
hibernate.search.Animal.0.indexName = Animal00
hibernate.search.Animal.3.indexBase = /usr/lucene/sharded
hibernate.search.Animal.3.indexName = Animal03
Copy to Clipboard Toggle word wrap

在上例中,配置使用默认的 id 字符串散列策略,并将 Animal 索引分片为 5 子索引。所有子索引都是文件系统实例,以及存储每个子索引的目录如下:

  • 对于 sub-index 0: /usr/lucene/indexes/Animal00 (共享 indexBase,但覆盖 indexName)
  • 对于子索引 1: /usr/lucene/indexes/Animal.1 (共享索引Base,默认 indexName)
  • 对于子索引 2: /usr/lucene/indexes/Animal.2 (共享 indexBase,默认 indexName)
  • 对于 sub-index 3: /usr/lucene/shared/Animal03 (覆盖索引Base,覆盖 indexName)
  • 对于子索引 4: /usr/lucene/indexes/Animal.4( 共享 indexBase,默认 indexName)

在实施 IndexShardingStrategy 时,可使用任何字段来确定分片选择。考虑为了处理删除、清除 和清除All 操作,实施可能需要返回一个或多个索引,而无需读取所有字段值或主标识符。在这种情况下,信息不足以选择一个索引,应该返回所有索引,以便将删除操作传播到所有可能包含要删除的文档的索引。

7.8.5. 自定义 Lucene 的 Scoring Formula

Lucene 允许用户通过扩展 org.apache.lucene.search.Similarity 来自定义其评分公式。此类中定义的抽象方法与计算文档 d 查询 q 分数的以下公式因素相符:

扩展 org.apache.lucene.search.Similarity,以自定义 Lucene 的评分公式。抽象方法与 用于计算 文档 d 查询分数的公式匹配,如下所示:

*score(q,d) = coord(q,d) · queryNorm(q) · ∑ ~t in q~ ( tf(t in d) ·
idf(t) ^2^ · t.getBoost() · norm(t,d) )*
Copy to Clipboard Toggle word wrap
Expand
factor描述

TF(t ind)

文档(d)中术语(t)的术语频率因素。

idf(t)

术语的反向文档频率。

coord(q,d)

根据在指定文档中找到多少查询术语的分数因素。

queryNorm(q)

用于在查询之间对分数进行可比较的规范化因素。

t.getBoost()

字段推动.

norm(t,d)

封装几个(索引时间)增高和长度因素。

本手册无法更加详细地解释此公式。如需更多信息,请参阅 Similarity 的 Java 文档。

Hibernate Search 提供三种方法来修改 Lucene 的相似性计算:

首先,您可以使用属性 hibernate.search.similarity 指定一个完全指定的类名称来设置默认的相似性。默认值为 org.apache.lucene.search.DefaultSimilarity。

您还可以通过设置相似性属性来覆盖用于特定索引 的相似性

hibernate.search.default.similarity = my.custom.Similarity
Copy to Clipboard Toggle word wrap

最后,您可以使用 @Similarity 注释覆盖类级别上的默认相似性。

@Entity
@Indexed
@Similarity(impl = DummySimilarity.class)
public class Book {
...
}
Copy to Clipboard Toggle word wrap

例如,让我们假设术语在文档中出现的频率并不重要。出现过多个术语的文档的评分应与多次出现的文档相同。在这种情况下,您的自定义方法 tf(float freq)应该返回 1.0。

警告

当两个实体共享相同的索引时,它们必须声明相同的相似实施。同一类层次结构中的类始终共享索引,因此不允许覆盖子类型中的相似性实施。

同样,通过索引设置和类级设置定义相似性(因为它们会发生冲突)也不有意义。此类配置将被拒绝。

7.8.6. 异常处理配置

Hibernate Search 允许您配置在索引过程中如何处理异常。如果没有提供配置,则默认将异常记录到日志输出。可以显式声明异常日志记录机制,如下所示:

hibernate.search.error_handler = log
Copy to Clipboard Toggle word wrap

默认异常处理适用于同步和异步索引。Hibernate Search 提供了一种简单的机制,可以覆盖默认的错误处理实施。

为了提供自己的实施,您必须实施 ErrorHandler 接口,它提供 handle(ErrorContext context) 方法。ErrorContext 提供了对主 LuceneWork 实例的引用、底层异常以及因为主要例外而无法处理的随后 LuceneWork 实例。

public interface ErrorContext  {
   List<LuceneWork> getFailingOperations();
   LuceneWork getOperationAtFault();
   Throwable getThrowable();
   boolean hasErrors();
}
Copy to Clipboard Toggle word wrap

要使用 Hibernate Search 注册此错误处理程序,您必须在配置属性中声明 ErrorHandler 实现的完全限定类名称:

hibernate.search.error_handler = CustomerErrorHandler
Copy to Clipboard Toggle word wrap
Red Hat logoGithubredditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。 了解我们当前的更新.

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

Theme

© 2026 Red Hat
返回顶部