7.8. 高级功能
7.8.1. 访问 SearchFactory 复制链接链接已复制到粘贴板!
SearchFactory 对象跟踪 Hibernate Search 的底层 Lucene 资源。它是原生访问 Lucene 的便捷方式。SearchFactory 可以从 FullTextSession 访问:
示例:访问 SearchFactory
FullTextSession fullTextSession = Search.getFullTextSession(regularSession); SearchFactory searchFactory = fullTextSession.getSearchFactory();
FullTextSession fullTextSession = Search.getFullTextSession(regularSession);
SearchFactory searchFactory = fullTextSession.getSearchFactory();
7.8.2. 使用 IndexReader 复制链接链接已复制到粘贴板!
Lucene 中的查询在 IndexReader 上执行。Hibernate 搜索可能会缓存索引读取器以最大化性能,或者提供其他有效策略来检索更新的 indexReader 最小化 I/O 操作。您的代码可以访问这些缓存的资源,但有几个要求。
示例:访问 IndexReader
在本例中,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");
IndexReader reader = searchFactory.getIndexReaderAccessor().open("Products.1", "Products.3");
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
hibernate.search.<indexName>.sharding_strategy.nbr_of_shards = 5
负责将数据拆分为 sub-indexes 是 indexShardingStrategy。默认分片策略会根据 ID 字符串表示法的散列值(由 FieldBridge 生成)来分割数据。这可确保比较平衡的分片。您可以通过实施自定义 IndexShardingStrategy 来替换默认策略。要使用自定义策略,您必须设置 hibernate.search.<indexName>.sharding_strategy 属性。
示例:指定自定义划分策略
hibernate.search.<indexName>.sharding_strategy = my.shardingstrategy.Implementation
hibernate.search.<indexName>.sharding_strategy = my.shardingstrategy.Implementation
IndexShardingStrategy 属性还允许通过选择针对哪个分片运行查询来优化搜索。通过激活过滤器,分片策略可以选择用于应答查询的分片的子集(IndexShardingStrategy.getIndexManagersForQuery),从而加快查询执行。
每个分片都有独立的 IndexManager,因此可以配置为使用不同的目录供应商和后端配置。以下示例中 Animal 实体的 IndexManager 索引名称是 Animal.0 到 Animal.4。换句话说,每个分片都有其自己的索引的名称,后跟 . (dot)及其索引号。
示例:对实体 Animal 进行划分配置
在上例中,配置使用默认的 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) )*
*score(q,d) = coord(q,d) · queryNorm(q) · ∑ ~t in q~ ( tf(t in d) ·
idf(t) ^2^ · t.getBoost() · norm(t,d) )*
| 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
hibernate.search.default.similarity = my.custom.Similarity
最后,您可以使用 @Similarity 注释覆盖类级别上的默认相似性。
例如,让我们假设术语在文档中出现的频率并不重要。出现过多个术语的文档的评分应与多次出现的文档相同。在这种情况下,您的自定义方法 tf(float freq)应该返回 1.0。
当两个实体共享相同的索引时,它们必须声明相同的相似实施。同一类层次结构中的类始终共享索引,因此不允许覆盖子类型中的相似性实施。
同样,通过索引设置和类级设置定义相似性(因为它们会发生冲突)也不有意义。此类配置将被拒绝。
7.8.6. 异常处理配置 复制链接链接已复制到粘贴板!
Hibernate Search 允许您配置在索引过程中如何处理异常。如果没有提供配置,则默认将异常记录到日志输出。可以显式声明异常日志记录机制,如下所示:
hibernate.search.error_handler = log
hibernate.search.error_handler = log
默认异常处理适用于同步和异步索引。Hibernate Search 提供了一种简单的机制,可以覆盖默认的错误处理实施。
为了提供自己的实施,您必须实施 ErrorHandler 接口,它提供 handle(ErrorContext context) 方法。ErrorContext 提供了对主 LuceneWork 实例的引用、底层异常以及因为主要例外而无法处理的随后 LuceneWork 实例。
要使用 Hibernate Search 注册此错误处理程序,您必须在配置属性中声明 ErrorHandler 实现的完全限定类名称:
hibernate.search.error_handler = CustomerErrorHandler
hibernate.search.error_handler = CustomerErrorHandler
7.8.7. 禁用 Hibernate Search 复制链接链接已复制到粘贴板!
可以根据需要部分或完全禁用 Hibernate 搜索.可以禁用 Hibernate Search 的索引,例如,如果索引是只读的,或者您更喜欢手动执行索引,而不是自动执行。也可以完全禁用 Hibernate 搜索,防止索引和搜索。
- 禁用索引
要禁用 Hibernate Search 索引,请将 indexing
_strategy配置选项更改为manual,然后重新启动 JBoss EAP。hibernate.search.indexing_strategy = manual
hibernate.search.indexing_strategy = manualCopy to Clipboard Copied! Toggle word wrap Toggle overflow - 完全禁用 Hibernate 搜索
要完全禁用 Hibernate 搜索,请通过将
autoregister_listeners配置选项更改为false来禁用所有侦听器,然后重新启动 JBoss EAP。hibernate.search.autoregister_listeners = false
hibernate.search.autoregister_listeners = falseCopy to Clipboard Copied! Toggle word wrap Toggle overflow