将 Hibernate Search 与 Hibernate ORM 和 Elasticsearch/OpenSearch 一起使用
您有一个基于 Hibernate ORM 的应用程序?您想为您的用户提供功能齐全的全文搜索?您来对地方了。
通过本指南,您将学会如何轻松地将实体同步到 Elasticsearch 或 OpenSearch 集群。我们还将探讨如何使用 Hibernate Search API 查询 Elasticsearch 或 OpenSearch 集群。
如果您想索引非 Hibernate ORM 实体的实体,请参阅此专用指南。 |
先决条件
要完成本指南,您需要
-
大约 20 分钟
-
一个 IDE
-
已安装 JDK 17+ 并正确配置了
JAVA_HOME
-
Apache Maven 3.9.9
-
一个正常工作的容器运行时(Docker 或 Podman)
-
如果您想使用它,可以选择 Quarkus CLI
-
如果您想构建本机可执行文件(或者如果您使用本机容器构建,则为 Docker),可以选择安装 Mandrel 或 GraalVM 并进行适当的配置
解决方案
我们建议您按照以下章节中的说明,逐步创建应用程序。但是,您可以直接转到完整的示例。
克隆 Git 存储库:git clone https://github.com/quarkusio/quarkus-quickstarts.git
,或下载存档。
解决方案位于 hibernate-search-orm-elasticsearch-quickstart
目录中。
提供的解决方案包含一些额外的元素,例如测试和测试基础架构。 |
创建 Maven 项目
首先,我们需要一个新项目。使用以下命令创建一个新项目
对于 Windows 用户
-
如果使用 cmd,(不要使用反斜杠
\
并将所有内容放在同一行上) -
如果使用 Powershell,请将
-D
参数用双引号括起来,例如"-DprojectArtifactId=hibernate-search-orm-elasticsearch-quickstart"
。
此命令生成一个 Maven 结构,导入以下扩展:
-
Hibernate ORM with Panache,
-
PostgreSQL JDBC 驱动程序,
-
Hibernate Search + Elasticsearch,
-
Quarkus REST(前身为 RESTEasy Reactive)和 Jackson。
如果您已经配置了 Quarkus 项目,可以通过在项目根目录中运行以下命令将 hibernate-search-orm-elasticsearch
扩展添加到项目中:
quarkus extension add hibernate-search-orm-elasticsearch
./mvnw quarkus:add-extension -Dextensions='hibernate-search-orm-elasticsearch'
./gradlew addExtension --extensions='hibernate-search-orm-elasticsearch'
这会将以下内容添加到您的 pom.xml
中
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-search-orm-elasticsearch</artifactId>
</dependency>
implementation("io.quarkus:quarkus-hibernate-search-orm-elasticsearch")
创建基础实体
首先,我们在 model
子包中创建 Hibernate ORM 实体 Book
和 Author
。
package org.acme.hibernate.search.elasticsearch.model;
import java.util.List;
import java.util.Objects;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.OneToMany;
import io.quarkus.hibernate.orm.panache.PanacheEntity;
@Entity
public class Author extends PanacheEntity { (1)
public String firstName;
public String lastName;
@OneToMany(mappedBy = "author", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) (2)
public List<Book> books;
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof Author)) {
return false;
}
Author other = (Author) o;
return Objects.equals(id, other.id);
}
@Override
public int hashCode() {
return 31;
}
}
1 | 我们使用 Hibernate ORM with Panache,这不是强制性的。 |
2 | 我们惰性加载这些元素,以便它们出现在 JSON 输出中。在实际应用中,您可能应该使用 DTO 方法。 |
package org.acme.hibernate.search.elasticsearch.model;
import java.util.Objects;
import jakarta.persistence.Entity;
import jakarta.persistence.ManyToOne;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.quarkus.hibernate.orm.panache.PanacheEntity;
@Entity
public class Book extends PanacheEntity {
public String title;
@ManyToOne
@JsonIgnore (1)
public Author author;
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof Book)) {
return false;
}
Book other = (Book) o;
return Objects.equals(id, other.id);
}
@Override
public int hashCode() {
return 31;
}
}
1 | 我们将此属性标记为 @JsonIgnore ,以避免在与 Jackson 序列化时出现无限循环。 |
初始化 REST 服务
虽然我们的 REST 服务尚未完全设置好,但我们可以用它需要的标准 CRUD 操作来初始化它。
创建 org.acme.hibernate.search.elasticsearch.LibraryResource
类。
package org.acme.hibernate.search.elasticsearch;
import java.util.List;
import java.util.Optional;
import jakarta.enterprise.event.Observes;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.PUT;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.core.MediaType;
import org.acme.hibernate.search.elasticsearch.model.Author;
import org.acme.hibernate.search.elasticsearch.model.Book;
import org.hibernate.search.mapper.orm.session.SearchSession;
import org.jboss.resteasy.reactive.RestForm;
import org.jboss.resteasy.reactive.RestQuery;
import io.quarkus.runtime.StartupEvent;
@Path("/library")
public class LibraryResource {
@PUT
@Path("book")
@Transactional
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public void addBook(@RestForm String title, @RestForm Long authorId) {
Author author = Author.findById(authorId);
if (author == null) {
return;
}
Book book = new Book();
book.title = title;
book.author = author;
book.persist();
author.books.add(book);
author.persist();
}
@DELETE
@Path("book/{id}")
@Transactional
public void deleteBook(Long id) {
Book book = Book.findById(id);
if (book != null) {
book.author.books.remove(book);
book.delete();
}
}
@PUT
@Path("author")
@Transactional
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public void addAuthor(@RestForm String firstName, @RestForm String lastName) {
Author author = new Author();
author.firstName = firstName;
author.lastName = lastName;
author.persist();
}
@POST
@Path("author/{id}")
@Transactional
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public void updateAuthor(Long id, @RestForm String firstName, @RestForm String lastName) {
Author author = Author.findById(id);
if (author == null) {
return;
}
author.firstName = firstName;
author.lastName = lastName;
author.persist();
}
@DELETE
@Path("author/{id}")
@Transactional
public void deleteAuthor(Long id) {
Author author = Author.findById(id);
if (author != null) {
author.delete();
}
}
}
这里没什么特别的:这只是 REST 服务中经典的 Hibernate ORM with Panache 操作。
事实上,有趣的部分是我们只需要添加很少的元素就可以让我们的全文搜索应用程序正常工作。
使用 Hibernate Search 注解
我们回到我们的实体。
为它们启用全文搜索功能就像添加一些注解一样简单。
让我们再次编辑 Book
实体以包含此内容:
package org.acme.hibernate.search.elasticsearch.model;
import java.util.Objects;
import jakarta.persistence.Entity;
import jakarta.persistence.ManyToOne;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.FullTextField;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.Indexed;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.quarkus.hibernate.orm.panache.PanacheEntity;
@Entity
@Indexed (1)
public class Book extends PanacheEntity {
@FullTextField(analyzer = "english") (2)
public String title;
@ManyToOne
@JsonIgnore
public Author author;
// Preexisting equals()/hashCode() methods
}
1 | 首先,我们使用 @Indexed 注解将我们的 Book 实体注册为全文索引的一部分。 |
2 | @FullTextField 注解声明了一个专门为全文搜索量身定制的索引字段。特别是,我们必须定义一个分析器来拆分和分析 token(~单词)——稍后会详细介绍。 |
现在我们的书籍已被索引,我们也可以对作者做同样的事情。
打开 Author
类并包含以下内容。
这里的情况非常相似:我们使用 @Indexed
、@FullTextField
和 @KeywordField
注解。
不过,有一些区别/补充。让我们来看看。
package org.acme.hibernate.search.elasticsearch.model;
import java.util.List;
import java.util.Objects;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.OneToMany;
import org.hibernate.search.engine.backend.types.Sortable;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.FullTextField;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.Indexed;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.IndexedEmbedded;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.KeywordField;
import io.quarkus.hibernate.orm.panache.PanacheEntity;
@Entity
@Indexed
public class Author extends PanacheEntity {
@FullTextField(analyzer = "name") (1)
@KeywordField(name = "firstName_sort", sortable = Sortable.YES, normalizer = "sort") (2)
public String firstName;
@FullTextField(analyzer = "name")
@KeywordField(name = "lastName_sort", sortable = Sortable.YES, normalizer = "sort")
public String lastName;
@OneToMany(mappedBy = "author", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
@IndexedEmbedded (3)
public List<Book> books;
// Preexisting equals()/hashCode() methods
}
1 | 我们使用与 Book 类似的 @FullTextField ,但您会注意到分析器不同——稍后会详细介绍。 |
2 | 正如您所见,我们可以为同一属性定义多个字段。在这里,我们定义了一个具有特定名称的 @KeywordField 。主要区别在于关键字字段不会被分词(字符串保留为一个单独的 token),但可以被规范化(即过滤)——稍后会详细介绍。此字段被标记为可排序,因为我们的目的是使用它来对作者进行排序。 |
3 | @IndexedEmbedded 的目的是将 Book 字段包含在 Author 索引中。在这种情况下,我们只使用默认配置:关联的 Book 实体的所有字段都包含在索引中(即 title 字段)。@IndexedEmbedded 的优点是能够自动重新索引 Author ,如果它的 Book 被更新了(得益于双向关系)。@IndexedEmbedded 也支持嵌套文档(使用 structure = NESTED 属性),但这里我们不需要。您还可以使用 includePaths /excludePaths 属性指定要嵌入到父索引中的字段,如果您不想要全部字段的话。 |
分析器和规范器
简介
分析是全文搜索的重要组成部分:它定义了文本在索引或构建搜索查询时如何被处理。
分析器的作用是将文本拆分为 token(~单词)并过滤它们(例如,将它们全部转换为小写并删除重音符号)。
规范器是一种特殊的分析器,它将输入保留为一个单独的 token。这对于排序或索引关键字特别有用。
有许多内置的分析器,但您也可以为自己的特定目的开发自定义分析器。
您可以在 Elasticsearch 文档的分析部分中了解更多关于 Elasticsearch 分析框架的信息。
定义使用的分析器
当我们向实体添加 Hibernate Search 注解时,我们定义了使用的分析器和规范器。通常
@FullTextField(analyzer = "english")
@FullTextField(analyzer = "name")
@KeywordField(name = "lastName_sort", sortable = Sortable.YES, normalizer = "sort")
我们使用
-
一个名为
name
的分析器用于人名, -
一个名为
english
的分析器用于书名, -
一个名为
sort
的规范器用于排序字段。
但我们还没有设置它们。
让我们看看如何使用 Hibernate Search 来实现。
设置分析器
这是一项简单的任务,我们只需要创建一个 ElasticsearchAnalysisConfigurer
的实现(并配置 Quarkus 来使用它,稍后会详细介绍)。
为了满足我们的需求,让我们创建以下实现:
package org.acme.hibernate.search.elasticsearch.config;
import org.hibernate.search.backend.elasticsearch.analysis.ElasticsearchAnalysisConfigurationContext;
import org.hibernate.search.backend.elasticsearch.analysis.ElasticsearchAnalysisConfigurer;
import io.quarkus.hibernate.search.orm.elasticsearch.SearchExtension;
@SearchExtension (1)
public class AnalysisConfigurer implements ElasticsearchAnalysisConfigurer {
@Override
public void configure(ElasticsearchAnalysisConfigurationContext context) {
context.analyzer("name").custom() (2)
.tokenizer("standard")
.tokenFilters("asciifolding", "lowercase");
context.analyzer("english").custom() (3)
.tokenizer("standard")
.tokenFilters("asciifolding", "lowercase", "porter_stem");
context.normalizer("sort").custom() (4)
.tokenFilters("asciifolding", "lowercase");
}
}
1 | 用 @SearchExtension 限定符注解配置器实现,以告知 Quarkus 它应该在默认持久化单元中使用,用于所有 Elasticsearch 索引(默认)。该注解也可以针对特定的持久化单元( |
2 | 这是一个简单的分析器,按空格分隔单词,通过其 ASCII 对应项删除任何非 ASCII 字符(从而删除重音符号)并将所有内容转换为小写。它在我们的示例中用于作者的姓名。 |
3 | 我们对这个更具侵略性,我们包含了一些词干提取:我们将能够搜索 mystery 并获得结果,即使索引的输入包含 mysteries 。这对于人名来说绝对太具侵略性了,但对于书名来说非常完美。 |
4 | 这是用于排序的规范器。与我们的第一个分析器非常相似,除了我们不分词,因为我们想要一个且只有一个 token。 |
或者,如果您出于任何原因无法或不想用
|
有关配置分析器的更多信息,请参阅参考文档的此部分。
为我们的 REST 服务添加全文功能
在我们现有的 LibraryResource
中,我们只需要注入 SearchSession
。
@Inject
SearchSession searchSession; (1)
1 | 注入 Hibernate Search 会话,它底层依赖于 EntityManager 。拥有多个持久化单元的应用程序可以使用 CDI 限定符 @io.quarkus.hibernate.orm.PersistenceUnit 来选择正确的会话:请参阅CDI 集成。 |
然后,奇迹就开始了。当我们向实体添加注解时,我们使它们可用于全文搜索;我们现在可以使用 Hibernate Search DSL 查询索引,只需添加以下方法(以及一些 import
)即可:
@GET
@Path("author/search")
@Transactional (1)
public List<Author> searchAuthors(@RestQuery String pattern, (2)
@RestQuery Optional<Integer> size) {
return searchSession.search(Author.class) (3)
.where(f ->
pattern == null || pattern.trim().isEmpty() ?
f.matchAll() : (4)
f.simpleQueryString()
.fields("firstName", "lastName", "books.title").matching(pattern) (5)
)
.sort(f -> f.field("lastName_sort").then().field("firstName_sort")) (6)
.fetchHits(size.orElse(20)); (7)
}
1 | 重要提示:我们需要一个事务性上下文来实现此方法。 |
2 | 使用 org.jboss.resteasy.reactive.RestQuery 注解类型来避免重复参数名。 |
3 | 我们指示我们要搜索 Author 。 |
4 | 我们创建一个谓词:如果模式为空,我们使用 matchAll() 谓词。 |
5 | 如果我们有一个有效的模式,我们在 firstName 、lastName 和 books.title 字段上创建一个 simpleQueryString() 谓词来匹配我们的模式。 |
6 | 我们定义结果的排序顺序。这里我们按姓氏排序,然后按名字排序。请注意,我们使用了为排序创建的特定字段。 |
7 | 获取 size 条命中,默认为 20 。显然,分页也受支持。 |
Hibernate Search DSL 支持 Elasticsearch 谓词的很大一部分(match、range、nested、phrase、spatial…)。随意使用自动完成功能探索 DSL。 当这些不够用时,您总可以通过 JSON 直接定义谓词。 |
自动数据初始化
为了本次演示的目的,让我们导入一个初始数据集。
让我们创建一个 src/main/resources/import.sql
文件,内容如下(我们将在稍后配置中引用它):
INSERT INTO author(id, firstname, lastname) VALUES (1, 'John', 'Irving');
INSERT INTO author(id, firstname, lastname) VALUES (2, 'Paul', 'Auster');
ALTER SEQUENCE author_seq RESTART WITH 3;
INSERT INTO book(id, title, author_id) VALUES (1, 'The World According to Garp', 1);
INSERT INTO book(id, title, author_id) VALUES (2, 'The Hotel New Hampshire', 1);
INSERT INTO book(id, title, author_id) VALUES (3, 'The Cider House Rules', 1);
INSERT INTO book(id, title, author_id) VALUES (4, 'A Prayer for Owen Meany', 1);
INSERT INTO book(id, title, author_id) VALUES (5, 'Last Night in Twisted River', 1);
INSERT INTO book(id, title, author_id) VALUES (6, 'In One Person', 1);
INSERT INTO book(id, title, author_id) VALUES (7, 'Avenue of Mysteries', 1);
INSERT INTO book(id, title, author_id) VALUES (8, 'The New York Trilogy', 2);
INSERT INTO book(id, title, author_id) VALUES (9, 'Mr. Vertigo', 2);
INSERT INTO book(id, title, author_id) VALUES (10, 'The Brooklyn Follies', 2);
INSERT INTO book(id, title, author_id) VALUES (11, 'Invisible', 2);
INSERT INTO book(id, title, author_id) VALUES (12, 'Sunset Park', 2);
INSERT INTO book(id, title, author_id) VALUES (13, '4 3 2 1', 2);
ALTER SEQUENCE book_seq RESTART WITH 14;
由于上述数据将在没有 Hibernate Search 的情况下插入数据库,因此它不会被索引——不像通过 Hibernate ORM 操作即将进行的更新,这些更新将自动同步到全文索引。
在我们现有的 LibraryResource
中,让我们添加以下内容(以及一些 import
)来索引这些初始数据:
如果您不手动导入数据库中的数据,则不需要此操作:然后,只有在您更改索引配置(添加新字段、更改分析器配置…)并且希望将新配置应用于现有数据时,才应使用批量索引器。 |
@Inject
SearchMapping searchMapping; (1)
void onStart(@Observes StartupEvent ev) throws InterruptedException { (2)
// only reindex if we imported some content
if (Book.count() > 0) {
searchMapping.scope(Object.class) (3)
.massIndexer() (4)
.startAndWait(); (5)
}
}
1 | 注入 Hibernate Search 的 SearchMapping ,它底层依赖于 EntityManagerFactory 。拥有多个持久化单元的应用程序可以使用 CDI 限定符 @io.quarkus.hibernate.orm.PersistenceUnit 来选择正确的会话:请参阅CDI 集成。 |
2 | 添加一个将在应用程序启动时执行的方法。 |
3 | 创建一个“搜索范围”,它定位所有扩展 Object 的已索引实体类型——即所有已索引的实体类型(Author 和 Book )。 |
4 | 创建 Hibernate Search 批量索引器的实例,该实例允许高效地索引大量数据(您可以对其进行微调以获得更好的性能)。 |
5 | 启动批量索引器并等待其完成。 |
配置应用程序
像往常一样,我们可以在 Quarkus 配置文件 application.properties
中配置所有内容。
编辑 src/main/resources/application.properties
并注入以下配置:
quarkus.datasource.db-kind=postgresql (1)
quarkus.hibernate-orm.sql-load-script=import.sql (2)
quarkus.hibernate-search-orm.elasticsearch.version=9 (3)
quarkus.hibernate-search-orm.indexing.plan.synchronization.strategy=sync (4)
%prod.quarkus.datasource.jdbc.url=jdbc:postgresql:///quarkus_test
%prod.quarkus.datasource.username=quarkus_test
%prod.quarkus.datasource.password=quarkus_test
%prod.quarkus.hibernate-orm.schema-management.strategy=create
%prod.quarkus.hibernate-search-orm.elasticsearch.hosts=localhost:9200 (5)
1 | 让我们创建一个 PostgreSQL 数据源。 |
2 | 我们在启动时加载一些初始数据(参见自动数据初始化)。 |
3 | 我们需要告知 Hibernate Search 我们将使用的 Elasticsearch 版本。这很重要,因为 Elasticsearch 映射语法在不同版本之间存在显著差异。由于映射是在构建时创建以减少启动时间,因此 Hibernate Search 无法连接到集群以自动检测版本。请注意,对于 OpenSearch,您需要将版本前缀为 opensearch: ;请参阅OpenSearch 兼容性。 |
4 | 这意味着我们在认为写入完成之前等待实体可搜索。在生产环境中,write-sync 默认设置将提供更好的性能。使用 sync 在测试中尤其重要,因为您需要实体立即可搜索。 |
5 | 对于开发和测试,我们依赖于开发服务,这意味着 Quarkus 将自动启动 PostgreSQL 数据库和 Elasticsearch 集群。但在生产模式下,我们将需要手动启动 PostgreSQL 数据库和 Elasticsearch 集群,这就是为什么我们在 prod 配置文件(%prod. 前缀)中为 Quarkus 提供此连接信息的原因。 |
由于我们依赖于开发服务,因此数据库和 Elasticsearch 模式将在每次应用程序启动时在测试和开发模式下自动删除并重新创建(除非 如果您出于任何原因无法使用开发服务,您将需要设置以下属性以获得类似的行为:
|
有关 Hibernate Search ORM 扩展配置的更多信息,请参阅配置参考。 |
创建一个前端
现在让我们添加一个简单的网页来与我们的 LibraryResource
进行交互。Quarkus 会自动服务位于 META-INF/resources
目录下的静态资源。在 src/main/resources/META-INF/resources
目录中,用此index.html 文件中的内容覆盖现有的 index.html
文件。
开始使用您的应用程序
您现在可以与您的 REST 服务交互
-
使用以下命令启动您的 Quarkus 应用程序
CLIquarkus dev
Maven./mvnw quarkus:dev
Gradle./gradlew --console=plain quarkusDev
-
打开浏览器访问
https://:8080/
。 -
搜索作者或书名(我们已经为您初始化了一些数据)。
-
创建新的作者和书籍,然后搜索它们。
如您所见,您的所有更新都会自动同步到 Elasticsearch 集群。
构建本机可执行文件
您可以使用常用命令构建本机可执行文件
quarkus build --native
./mvnw install -Dnative
./gradlew build -Dquarkus.native.enabled=true
与原生可执行文件编译一样,此操作会消耗大量内存。 在构建原生可执行文件时停止两个容器,并在完成后重新启动它们可能更安全。 |
运行原生可执行文件就像执行 ./target/hibernate-search-orm-elasticsearch-quickstart-1.0.0-SNAPSHOT-runner
一样简单。
然后您可以将浏览器指向 https://:8080/
并使用您的应用程序。
启动比平时稍慢:这主要是由于我们在每次启动时都会删除并重新创建数据库模式和 Elasticsearch 映射。我们还注入了一些数据并执行了批量索引器。 在实际应用中,您显然不会在每次启动时都这样做。 |
开发服务(无配置的数据存储)
Quarkus 支持一项名为开发服务的功能,该功能允许您在没有任何配置的情况下启动各种容器。
在 Elasticsearch 的情况下,此支持扩展到了默认的 Elasticsearch 连接。实际上,这意味着如果您尚未配置 quarkus.hibernate-search-orm.elasticsearch.hosts
,Quarkus 将在运行测试或在开发模式下自动启动 Elasticsearch 容器并自动配置连接。
当运行应用程序的生产版本时,需要像往常一样配置 Elasticsearch 连接,因此如果您想在 application.properties
中包含生产数据库配置并继续使用开发服务,我们建议您使用 %prod.
配置文件来定义您的 Elasticsearch 设置。
Elasticsearch 的开发服务目前无法同时启动多个集群,因此它只适用于默认持久化单元的默认后端:命名持久化单元或命名后端将无法利用 Elasticsearch 的开发服务。 |
有关更多信息,您可以阅读 Elasticsearch 开发服务指南。
编程映射
如果由于某种原因无法将 Hibernate Search 注解添加到实体,则可以改用编程方式应用映射。编程映射通过映射配置器(HibernateOrmSearchMappingConfigurer
)公开的 ProgrammaticMappingConfigurationContext
进行配置。
映射配置器( |
下面是一个应用编程映射的映射配置器的示例:
package org.acme.hibernate.search.elasticsearch.config;
import org.hibernate.search.mapper.orm.mapping.HibernateOrmMappingConfigurationContext;
import org.hibernate.search.mapper.orm.mapping.HibernateOrmSearchMappingConfigurer;
import org.hibernate.search.mapper.pojo.mapping.definition.programmatic.TypeMappingStep;
import io.quarkus.hibernate.search.orm.elasticsearch.SearchExtension;
@SearchExtension (1)
public class CustomMappingConfigurer implements HibernateOrmSearchMappingConfigurer {
@Override
public void configure(HibernateOrmMappingConfigurationContext context) {
TypeMappingStep type = context.programmaticMapping() (2)
.type(SomeIndexedEntity.class); (3)
type.indexed() (4)
.index(SomeIndexedEntity.INDEX_NAME); (5)
type.property("id").documentId(); (6)
type.property("text").fullTextField(); (7)
}
}
1 | 用 @SearchExtension 限定符注解配置器实现,以告知 Quarkus 它应该被 Hibernate Search 用于默认持久化单元。该注解也可以针对特定的持久化单元( |
2 | 访问编程映射上下文。 |
3 | 为 SomeIndexedEntity 实体创建映射步骤。 |
4 | 将 SomeIndexedEntity 实体定义为已索引。 |
5 | 为 SomeIndexedEntity 实体提供索引名称。 |
6 | 定义文档 ID 属性。 |
7 | 为 text 属性定义一个全文搜索字段。 |
或者,如果您出于任何原因无法或不想用
|
OpenSearch 兼容性
Hibernate Search 与 Elasticsearch 和 OpenSearch 都兼容,但默认情况下它假定正在与 Elasticsearch 集群工作。
为了让 Hibernate Search 与 OpenSearch 集群一起工作,请将配置的版本前缀为 opensearch:
,如下所示。
quarkus.hibernate-search-orm.elasticsearch.version=opensearch:3.0
所有其他配置选项和 API 与 Elasticsearch 完全相同。
您可以在 Hibernate Search 参考文档的此部分中找到有关兼容的 Elasticsearch 发行版和版本的信息。
多个持久化单元
配置多个持久化单元
使用 Hibernate ORM 扩展,您可以设置多个持久化单元,每个持久化单元都有自己的数据源和配置。
如果您声明了多个持久化单元,您也将为每个持久化单元单独配置 Hibernate Search。
quarkus.hibernate-search-orm.
命名空间根目录下的属性定义了默认持久化单元。例如,以下代码片段定义了一个默认数据源和一个默认持久化单元,并将该持久化单元的 Elasticsearch 主机设置为 es1.mycompany.com:9200
。
quarkus.datasource.db-kind=h2
quarkus.datasource.jdbc.url=jdbc:h2:mem:default;DB_CLOSE_DELAY=-1
quarkus.hibernate-search-orm.elasticsearch.hosts=es1.mycompany.com:9200
quarkus.hibernate-search-orm.elasticsearch.version=9
使用基于 Map 的方法,也可以配置命名持久化单元:
quarkus.datasource."users".db-kind=h2 (1)
quarkus.datasource."users".jdbc.url=jdbc:h2:mem:users;DB_CLOSE_DELAY=-1
quarkus.datasource."inventory".db-kind=h2 (2)
quarkus.datasource."inventory".jdbc.url=jdbc:h2:mem:inventory;DB_CLOSE_DELAY=-1
quarkus.hibernate-orm."users".datasource=users (3)
quarkus.hibernate-orm."users".packages=org.acme.model.user
quarkus.hibernate-orm."inventory".datasource=inventory (4)
quarkus.hibernate-orm."inventory".packages=org.acme.model.inventory
quarkus.hibernate-search-orm."users".elasticsearch.hosts=es1.mycompany.com:9200 (5)
quarkus.hibernate-search-orm."users".elasticsearch.version=9
quarkus.hibernate-search-orm."inventory".elasticsearch.hosts=es2.mycompany.com:9200 (6)
quarkus.hibernate-search-orm."inventory".elasticsearch.version=9
1 | 定义一个名为 users 的数据源。 |
2 | 定义一个名为 inventory 的数据源。 |
3 | 定义一个名为 users 的持久化单元,指向 users 数据源。 |
4 | 定义一个名为 inventory 的持久化单元,指向 inventory 数据源。 |
5 | 为 users 持久化单元配置 Hibernate Search,将该持久化单元的 Elasticsearch 主机设置为 es1.mycompany.com:9200 。 |
6 | 为 inventory 持久化单元配置 Hibernate Search,将该持久化单元的 Elasticsearch 主机设置为 es2.mycompany.com:9200 。 |
将模型类附加到持久化单元
对于每个持久化单元,Hibernate Search 将只考虑附加到该持久化单元的已索引实体。实体通过配置 Hibernate ORM 扩展来附加到持久化单元。
CDI 集成
注入入口点
您可以使用 CDI 注入 Hibernate Search 的主要入口点 SearchSession
和 SearchMapping
。
@Inject
SearchSession searchSession;
这将注入默认持久化单元的 SearchSession
。
要注入命名持久化单元(例如我们示例中的 users
)的 SearchSession
,只需添加一个限定符。
@Inject
@PersistenceUnit("users") (1)
SearchSession searchSession;
1 | 这是 @io.quarkus.hibernate.orm.PersistenceUnit 注解。 |
您可以使用完全相同的机制注入命名持久化单元的 SearchMapping
。
@Inject
@PersistenceUnit("users")
SearchMapping searchMapping;
插入自定义组件
Hibernate ORM 扩展的 Quarkus 扩展将自动将用 @SearchExtension
注解的组件注入到 Hibernate Search 中。
该注解可以选择性地针对特定的持久化单元(@SearchExtension(persistenceUnit = "nameOfYourPU")
)、后端(@SearchExtension(backend = "nameOfYourBackend")
)、索引(@SearchExtension(index = "nameOfYourIndex")
)或它们的组合(@SearchExtension(persistenceUnit = "nameOfYourPU", backend = "nameOfYourBackend", index = "nameOfYourIndex")
),当它对于被注入的组件类型有意义时。
此功能可用于以下组件类型:
org.hibernate.search.engine.reporting.FailureHandler
-
一个应该被通知在后台进程(主要是索引操作)中发生的任何失败的组件。
范围:每个持久化单元一个。
有关更多信息,请参阅参考文档的这一部分。
org.hibernate.search.mapper.orm.mapping.HibernateOrmSearchMappingConfigurer
-
一个用于配置 Hibernate Search 映射的组件,特别是以编程方式。
范围:每个持久化单元一个或多个。
有关更多信息,请参阅本指南的此部分。
org.hibernate.search.mapper.pojo.work.IndexingPlanSynchronizationStrategy
-
一个用于配置应用程序线程和索引之间如何同步的组件。
范围:每个持久化单元一个。
有关更多信息,请参阅参考文档的这一部分。
org.hibernate.search.backend.elasticsearch.analysis.ElasticsearchAnalysisConfigurer
-
一个用于配置全文分析(例如分析器、规范器)的组件。
范围:每个后端一个或多个。
有关更多信息,请参阅本指南的此部分。
org.hibernate.search.backend.elasticsearch.index.layout.IndexLayoutStrategy
-
一个用于配置 Elasticsearch 布局的组件:索引名称、索引别名等。
范围:每个后端一个。
有关更多信息,请参阅参考文档的此章节。
离线启动
默认情况下,Hibernate Search 在启动时会向 Elasticsearch 集群发送一些请求。如果 Elasticsearch 集群在 Hibernate Search 启动时未运行,这可能会导致启动失败。
为了解决这个问题,您可以配置 Hibernate Search 以便在启动时不发送任何请求:
-
通过将配置属性
quarkus.hibernate-search-orm.elasticsearch.version-check.enabled
设置为false
来禁用启动时的 Elasticsearch 版本检查。 -
通过将配置属性
quarkus.hibernate-search-orm.schema-management.strategy
设置为none
来禁用启动时的模式管理。
当然,即使有了这个配置,在 Elasticsearch 集群变得可访问之前,Hibernate Search 仍然无法索引任何内容或运行搜索查询。
如果您通过将 有关更多信息,请参阅参考文档的此部分。 |
通过出站轮询协调
通过出站轮询协调被认为是预览版。 在预览阶段,向后兼容性和在生态系统中的存在性不被保证。特定改进可能需要更改配置或 API,甚至存储格式,并且计划成为稳定版本的工作正在进行中。欢迎在我们的邮件列表或我们的GitHub 问题跟踪器上提供反馈。 |
虽然在分布式应用程序中使用 Hibernate Search 和 Elasticsearch 在技术上是可能的,但默认情况下它们存在一些限制。
这些限制是由于 Hibernate Search 默认不协调线程或应用程序节点之间的关系造成的。
为了消除这些限制,您可以使用 outbox-polling
协调策略。此策略会在数据库中创建一个出站表来推送实体更改事件,并依赖后台处理器来消耗这些事件并执行索引。
要启用 outbox-polling
协调策略,需要一个额外的扩展:
quarkus extension add hibernate-search-orm-outbox-polling
./mvnw quarkus:add-extension -Dextensions='hibernate-search-orm-outbox-polling'
./gradlew addExtension --extensions='hibernate-search-orm-outbox-polling'
一旦扩展就位,您就需要通过将 quarkus.hibernate-search-orm.coordination.strategy
设置为 outbox-polling
来显式选择 outbox-polling
策略。
最后,您需要确保 Hibernate Search 添加的 Hibernate ORM 实体(代表出站和代理)在您的数据库中具有相应的表/序列:
-
如果您刚刚开始使用您的应用程序并打算让 Hibernate ORM 生成您的数据库模式,那么不用担心:Hibernate Search 所需的实体将包含在生成的模式中。
-
否则,您必须手动修改您的模式以添加必要的表/序列。
完成上述步骤后,您就可以使用带有出站的 Hibernate Search 了。不要更改任何代码,只需启动您的应用程序:它会自动检测何时多个应用程序连接到同一数据库,并相应地协调索引更新。
当使用 但是,有一个关键区别:索引更新必然是异步的;它们保证*最终*会发生,但不会立即发生。 这意味着尤其重要的是,当使用 此行为与 Elasticsearch 的近实时搜索以及推荐的 Hibernate Search 使用方式一致,即使在禁用协调时也是如此。 |
有关 Hibernate Search 中协调的更多信息,请参阅参考文档的此部分。
有关与协调相关的配置选项的更多信息,请参阅协调与出站轮询的配置。
AWS 请求签名
如果您需要使用亚马逊的托管 Elasticsearch 服务,您会发现它需要一种专有的身份验证方法,涉及请求签名。
您可以通过向项目中添加专用扩展并进行配置来在 Hibernate Search 中启用 AWS 请求签名。
管理端点
Hibernate Search 的管理端点被认为是预览版。 在预览阶段,向后兼容性和在生态系统中的存在性不被保证。特定改进可能需要更改配置或 API,甚至存储格式,并且计划成为稳定版本的工作正在进行中。欢迎在我们的邮件列表或我们的GitHub 问题跟踪器上提供反馈。 |
Hibernate Search 扩展提供了一个 HTTP 端点,用于通过管理接口重新索引数据。默认情况下,此端点不可用。可以通过配置属性启用它,如下所示。
quarkus.management.enabled=true (1)
quarkus.hibernate-search-orm.management.enabled=true (2)
1 | 启用管理接口。 |
2 | 启用 Hibernate Search 特定的管理端点。 |
启用管理端点后,可以通过 /q/hibernate-search/reindex
重新索引数据,其中 /q
是默认的管理根路径,/hibernate-search
是 Hibernate Search 的默认管理根路径。可以通过配置属性更改(/hibernate-search
),如下所示。
quarkus.hibernate-search-orm.management.root-path=custom-root-path (1)
1 | 为 Hibernate Search 的管理端点使用自定义 custom-root-path 路径。如果使用默认的管理根路径,则重新索引路径将变为 /q/custom-root-path/reindex 。 |
此端点仅接受 POST
请求,且 application/json
为内容类型。如果提交空的请求体,则所有已索引的实体都将被重新索引。如果只需要重新索引一部分实体,或者需要自定义底层批量索引器的配置,则可以通过请求体传递这些信息,如下所示。
{
"filter": {
"types": ["EntityName1", "EntityName2", "EntityName3", ...], (1)
},
"massIndexer":{
"typesToIndexInParallel": 1, (2)
}
}
1 | 一组应该被重新索引的实体名称。如果未指定或为空,则所有实体类型都将被重新索引。 |
2 | 设置并行索引的实体类型数量。 |
下面提供了可能的过滤器和可用批量索引器配置的完整列表。
{
"filter": { (1)
"types": ["EntityName1", "EntityName2", "EntityName3", ...], (2)
"tenants": ["tenant1", "tenant2", ...] (3)
},
"massIndexer":{ (4)
"typesToIndexInParallel": 1, (5)
"threadsToLoadObjects": 6, (6)
"batchSizeToLoadObjects": 10, (7)
"cacheMode": "IGNORE", (8)
"mergeSegmentsOnFinish": false, (9)
"mergeSegmentsAfterPurge": true, (10)
"dropAndCreateSchemaOnStart": false, (11)
"purgeAllOnStart": true, (12)
"idFetchSize": 100, (13)
"transactionTimeout": 100000, (14)
}
}
1 | 过滤器对象,允许限制重新索引的范围。 |
2 | 一组应该被重新索引的实体名称。如果未指定或为空,则所有实体类型都将被重新索引。 |
3 | 一组租户 ID,以防多租户。如果未指定或为空,则所有租户都将被重新索引。 |
4 | 批量索引器配置对象。 |
5 | 设置并行索引的实体类型数量。 |
6 | 设置加载根实体所使用的线程数。 |
7 | 设置加载根实体所使用的批处理大小。 |
8 | 设置数据加载任务的缓存交互模式。 |
9 | 索引完成后,是否将每个索引合并为一个段。 |
10 | 在索引之前,在首次索引清除后,是否将每个索引合并为一个段。 |
11 | 是否在索引之前删除并重新创建索引及其模式(如果存在)。 |
12 | 是否在索引之前从索引中删除所有实体。 |
13 | 指定加载要索引对象的 ID 时要使用的获取大小。 |
14 | 指定加载要重新索引的 ID 和实体事务的超时时间。 请注意,JSON 中的所有属性都是可选的,并且应仅使用所需的属性。 |
有关批量索引器配置的更多详细信息,请参阅 Hibernate Search 参考文档的相应部分。
提交重新索引请求将触发后台索引。批量索引进度将出现在应用程序日志中。出于测试目的,了解索引何时完成可能很有用。将 wait_for=finished
查询参数添加到 URL 将导致管理端点返回分块响应,报告索引何时开始以及何时完成。
当处理多个持久化单元时,可以通过 persistence_unit
查询参数提供要重新索引的持久化单元的名称:/q/hibernate-search/reindex?persistence_unit=non-default-persistence-unit
。
常见问题解答
为什么只支持 Elasticsearch?
Hibernate Search 同时支持 Lucene 后端和 Elasticsearch 后端。
在 Quarkus 的上下文中,为了构建可扩展的应用程序,我们认为后者更有意义。因此,我们将其作为重点。
目前我们不计划在 Quarkus 中支持 Lucene 后端,尽管 Quarkiverse 中有一个跟踪此类实现的 issue:quarkiverse/quarkus-hibernate-search-extras#179。
Hibernate Search with Hibernate ORM 的配置参考
主配置
构建时固定的配置属性 - 所有其他配置属性都可以在运行时覆盖
配置属性 |
类型 |
默认 |
||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Hibernate Search 在*构建期间*是否启用。 如果在构建期间禁用 Hibernate Search,将跳过所有与 Hibernate Search 相关的处理,但在运行时将无法激活 Hibernate Search: 环境变量: 显示更多 |
布尔值 |
|
||||||||||||||||||||||||||||||||
一个 bean 引用,指向应该被通知后台进程(主要是索引操作)中发生的任何失败的组件。 引用的 bean 必须实现 有关更多信息,请参阅参考文档的这一部分。
环境变量: 显示更多 |
字符串 |
|||||||||||||||||||||||||||||||||
显示更多 |
字符串 |
|
||||||||||||||||||||||||||||||||
一个或多个 bean 引用,指向用于配置 Hibernate Search 映射的组件,特别是以编程方式。 引用的 bean 必须实现 有关映射配置器如何用于应用编程映射的示例,请参阅编程映射。
环境变量: 显示更多 |
字符串列表 |
|||||||||||||||||||||||||||||||||
Hibernate Search 在运行时对于此持久化单元是否应处于活动状态。 如果 Hibernate Search 未处于活动状态,它将不会索引 Hibernate ORM 实体,并且无法访问相关持久化单元的 SearchMapping/SearchSession 来进行搜索或其他操作。 请注意,如果 Hibernate Search 被禁用(即 环境变量: 显示更多 |
布尔值 |
|
||||||||||||||||||||||||||||||||
模式管理策略,控制如何在启动和关闭时创建、更新、验证或删除索引及其模式。 可用值
有关更多信息,请参阅参考文档的此部分。 环境变量: 显示更多 |
|
|
||||||||||||||||||||||||||||||||
在执行搜索查询时加载实体时使用的策略。 环境变量: 显示更多 |
|
|
||||||||||||||||||||||||||||||||
在执行搜索查询时加载实体时使用的获取大小。 环境变量: 显示更多 |
整数 |
|
||||||||||||||||||||||||||||||||
如何在应用程序线程和索引之间进行同步,尤其是在依赖于实体更改时(隐式)侦听器触发的索引,以及在使用显式的 定义数据库事务提交后,在恢复应用程序线程之前,索引应完成到何种程度。
可用值
此属性还接受指向 有关更多信息,请参阅参考文档的这一部分。
环境变量: 显示更多 |
字符串 |
|
||||||||||||||||||||||||||||||||
当启用多租户时,应用程序可能使用的所有租户标识符的详尽列表。 主要用于使用 {@code outbox-polling} 协调策略,因为它涉及为每个租户设置一个后台处理器。 环境变量: 显示更多 |
字符串列表 |
|||||||||||||||||||||||||||||||||
类型 |
默认 |
|||||||||||||||||||||||||||||||||
集群中使用的 Elasticsearch 版本。 由于 schema 是在没有连接到服务器的情况下生成的,因此此项是必需的。 它不必是精确的版本(例如,可以是 这里没有经验法则,因为它取决于 Elasticsearch 版本引入的 schema 不兼容性。无论如何,如果出现问题,当 Hibernate Search 尝试连接到集群时,您将收到错误。 环境变量: 显示更多 |
ElasticsearchVersion |
|||||||||||||||||||||||||||||||||
classpath 中文件的路径,该文件包含自定义索引设置,以便在创建 Elasticsearch 索引时包含在索引定义中。 提供的设置将与 Hibernate Search 生成的设置合并,包括分析器定义。当分析器通过分析配置器和这些自定义设置进行配置时,行为是未定义的;不应依赖于此。 有关更多信息,请参阅参考文档的此章节。 环境变量: 显示更多 |
字符串 |
|||||||||||||||||||||||||||||||||
classpath 中文件的路径,该文件包含自定义索引映射,以便在创建 Elasticsearch 索引时包含在索引定义中。 该文件不需要(通常也不应该)包含完整的映射:Hibernate Search 将自动在给定的映射中注入缺失的属性(索引字段)。 有关更多信息,请参阅参考文档的此章节。 环境变量: 显示更多 |
字符串 |
|||||||||||||||||||||||||||||||||
一个或多个 bean 引用,指向用于配置全文分析(例如分析器、规范器)的组件。 引用的 Bean 必须实现 有关更多信息,请参阅设置分析器。
环境变量: 显示更多 |
字符串列表 |
|||||||||||||||||||||||||||||||||
Elasticsearch 服务器的主机列表。 环境变量: 显示更多 |
字符串列表 |
|
||||||||||||||||||||||||||||||||
联系 Elasticsearch 服务器时使用的协议。 设置为 "https" 以启用 SSL/TLS。 环境变量: 显示更多 |
|
|
||||||||||||||||||||||||||||||||
用于身份验证的用户名。 环境变量: 显示更多 |
字符串 |
|||||||||||||||||||||||||||||||||
用于身份验证的密码。 环境变量: 显示更多 |
字符串 |
|||||||||||||||||||||||||||||||||
建立与 Elasticsearch 服务器的连接时的超时时间。 环境变量: 显示更多 |
|
|||||||||||||||||||||||||||||||||
从 Elasticsearch 服务器读取响应时的超时时间。 环境变量: 显示更多 |
|
|||||||||||||||||||||||||||||||||
执行对 Elasticsearch 服务器的请求时的超时时间。 这包括等待连接可用、发送请求和读取响应所需的时间。 环境变量: 显示更多 |
||||||||||||||||||||||||||||||||||
到所有 Elasticsearch 服务器的最大连接数。 环境变量: 显示更多 |
整数 |
|
||||||||||||||||||||||||||||||||
每个 Elasticsearch 服务器的最大连接数。 环境变量: 显示更多 |
整数 |
|
||||||||||||||||||||||||||||||||
定义是否启用自动发现。 环境变量: 显示更多 |
布尔值 |
|
||||||||||||||||||||||||||||||||
节点列表的刷新间隔。 环境变量: 显示更多 |
|
|||||||||||||||||||||||||||||||||
分配给后端的线程池的大小。 请注意,该数字是每个后端,而不是每个索引。添加更多索引不会添加更多线程。 由于此线程池中发生的所有操作都是非阻塞的,因此将其大小提高到 JVM 可用的处理器核心数以上不会带来明显的性能提升。改变此设置的唯一原因是减少线程数;例如,在只有一个索引、一个索引队列且运行在具有 64 个处理器核心的机器上的应用程序中,您可能希望降低线程数。 默认为启动时 JVM 可用的处理器核心数。 环境变量: 显示更多 |
整数 |
|||||||||||||||||||||||||||||||||
是否忽略部分分片故障 ( 环境变量: 显示更多 |
布尔值 |
|
||||||||||||||||||||||||||||||||
Hibernate Search 是否应在启动时检查 Elasticsearch 集群的版本。 如果 Elasticsearch 集群在启动时可能不可用,请设置为 环境变量: 显示更多 |
布尔值 |
|
||||||||||||||||||||||||||||||||
启动时所需的最小Elasticsearch 集群状态。 环境变量: 显示更多 |
|
|
||||||||||||||||||||||||||||||||
在引导失败之前,我们应该等待状态多长时间。 环境变量: 显示更多 |
|
|||||||||||||||||||||||||||||||||
分配给每个索引的索引队列数。 更高的值将导致更多连接并行使用,这可能导致更高的索引吞吐量,但有使 Elasticsearch 过载的风险,即溢出其 HTTP 请求缓冲区并触发断路器,导致 Elasticsearch 放弃某些请求并导致索引失败。 环境变量: 显示更多 |
整数 |
|
||||||||||||||||||||||||||||||||
索引队列的大小。 较低的值可能导致内存使用量较低,特别是如果有很多队列,但值太低会降低达到最大批量大小的可能性,并增加应用程序线程因队列已满而阻塞的可能性,这可能导致索引吞吐量降低。 环境变量: 显示更多 |
整数 |
|
||||||||||||||||||||||||||||||||
处理索引队列时创建的批量请求的最大大小。 更高的值将导致每个发送到 Elasticsearch 的 HTTP 请求发送更多文档,这可能导致更高的索引吞吐量,但有使 Elasticsearch 过载的风险,即溢出其 HTTP 请求缓冲区并触发断路器,导致 Elasticsearch 放弃某些请求并导致索引失败。 请注意,将此数字提高到队列大小以上没有效果,因为批量请求不能包含比队列中包含的请求更多的请求。 环境变量: 显示更多 |
整数 |
|
||||||||||||||||||||||||||||||||
一个用于配置 Elasticsearch 布局的组件的 bean 引用:索引名称、索引别名等。 引用的 Bean 必须实现 可用的内置实现
有关更多信息,请参阅参考文档的此章节。
环境变量: 显示更多 |
字符串 |
|||||||||||||||||||||||||||||||||
类型 |
默认 |
|||||||||||||||||||||||||||||||||
classpath 中文件的路径,该文件包含自定义索引设置,以便在创建 Elasticsearch 索引时包含在索引定义中。 提供的设置将与 Hibernate Search 生成的设置合并,包括分析器定义。当分析器通过分析配置器和这些自定义设置进行配置时,行为是未定义的;不应依赖于此。 有关更多信息,请参阅参考文档的此章节。 环境变量: 显示更多 |
字符串 |
|||||||||||||||||||||||||||||||||
classpath 中文件的路径,该文件包含自定义索引映射,以便在创建 Elasticsearch 索引时包含在索引定义中。 该文件不需要(通常也不应该)包含完整的映射:Hibernate Search 将自动在给定的映射中注入缺失的属性(索引字段)。 有关更多信息,请参阅参考文档的此章节。 环境变量: 显示更多 |
字符串 |
|||||||||||||||||||||||||||||||||
一个或多个 bean 引用,指向用于配置全文分析(例如分析器、规范器)的组件。 引用的 Bean 必须实现 有关更多信息,请参阅设置分析器。
环境变量: 显示更多 |
字符串列表 |
|||||||||||||||||||||||||||||||||
启动时所需的最小Elasticsearch 集群状态。 环境变量: 显示更多 |
|
|
||||||||||||||||||||||||||||||||
在引导失败之前,我们应该等待状态多长时间。 环境变量: 显示更多 |
|
|||||||||||||||||||||||||||||||||
分配给每个索引的索引队列数。 更高的值将导致更多连接并行使用,这可能导致更高的索引吞吐量,但有使 Elasticsearch 过载的风险,即溢出其 HTTP 请求缓冲区并触发断路器,导致 Elasticsearch 放弃某些请求并导致索引失败。 环境变量: 显示更多 |
整数 |
|
||||||||||||||||||||||||||||||||
索引队列的大小。 较低的值可能导致内存使用量较低,特别是如果有很多队列,但值太低会降低达到最大批量大小的可能性,并增加应用程序线程因队列已满而阻塞的可能性,这可能导致索引吞吐量降低。 环境变量: 显示更多 |
整数 |
|
||||||||||||||||||||||||||||||||
处理索引队列时创建的批量请求的最大大小。 更高的值将导致每个发送到 Elasticsearch 的 HTTP 请求发送更多文档,这可能导致更高的索引吞吐量,但有使 Elasticsearch 过载的风险,即溢出其 HTTP 请求缓冲区并触发断路器,导致 Elasticsearch 放弃某些请求并导致索引失败。 请注意,将此数字提高到队列大小以上没有效果,因为批量请求不能包含比队列中包含的请求更多的请求。 环境变量: 显示更多 |
整数 |
|
||||||||||||||||||||||||||||||||
类型 |
默认 |
|||||||||||||||||||||||||||||||||
重新索引端点的根路径。此值将解析为相对于 环境变量: 显示更多 |
字符串 |
|
||||||||||||||||||||||||||||||||
如果管理界面已开启,则重新索引端点将在管理界面下发布。此属性允许通过将其设置为 环境变量: 显示更多 |
布尔值 |
|
关于 Duration 格式
要编写持续时间值,请使用标准的 您还可以使用简化的格式,以数字开头
在其他情况下,简化格式将被转换为
|
关于 bean 引用
首先,请注意在配置属性中引用 bean 是可选的,实际上是不推荐的:您可以通过用 如果您确实想使用配置属性中的字符串值来引用 bean,请知道字符串会被解析;以下是最常见的格式:
也接受其他格式,但仅适用于高级用例。有关更多信息,请参阅 Hibernate Search 参考文档的此部分。 |
协调与出站轮询的配置
这些配置属性需要一个额外的扩展。请参阅通过出站轮询协调。 |
构建时固定的配置属性 - 所有其他配置属性都可以在运行时覆盖
配置属性 |
类型 |
默认 |
---|---|---|
事件处理器是否已启用,即事件是否将被处理以在此应用程序实例上执行自动重新索引。 这可以设置为 有关更多信息,请参阅参考文档的此部分。 环境变量: 显示更多 |
布尔值 |
|
将构成实体更改事件处理分区的分片总数。 默认情况下,分片是动态的,因此不需要设置此属性。 如果您想明确控制分片的数量和分配,则必须配置静态分片,然后设置此属性以及分配的分片(请参阅 有关事件处理器分片的更多信息,请参阅参考文档的此部分。 环境变量: 显示更多 |
整数 |
|
在将构成实体变更事件分区的分片中,由此应用程序实例处理的分片。 默认情况下,分片是动态的,因此不需要设置此属性。 如果您想显式控制分片的数量和分配,则必须配置静态分片,然后设置此属性以及总分片数是必需的。 分片通过范围 有关事件处理器分片的更多信息,请参阅参考文档的此部分。 环境变量: 显示更多 |
int 列表 |
|
在查询外发事件表没有返回任何事件后,等待下一次查询的间隔。 较低的值会缩短变更反映在索引中的时间,但会在没有新事件时增加数据库的压力。 有关更多信息,请参阅参考文档的此部分。 环境变量: 显示更多 |
|
|
事件处理器在必须执行“脉冲”(更新和检查代理表中的注册)之前可以轮询事件的时间。 脉冲间隔必须设置为介于轮询间隔和到期间隔的三分之一(1/3)之间的值。 较低的值(接近轮询间隔)意味着当节点加入或离开集群时,浪费的时间更少,并且因为事件处理器被错误地视为已断开连接而浪费时间处理事件的风险降低,但由于更频繁地检查代理列表,数据库压力更大。 较高的值(接近到期间隔)意味着当节点加入或离开集群时,浪费的时间更多,并且因为事件处理器被错误地视为已断开连接而浪费时间处理事件的风险增加,但由于不太频繁地检查代理列表,数据库压力更小。 有关更多信息,请参阅参考文档的此部分。 环境变量: 显示更多 |
|
|
事件处理器的“脉冲”在被视为处理器已断开连接并强制将其从集群中移除之前保持有效的时长。 到期间隔必须设置为至少是脉冲间隔的 3 倍的值。 较低的值(接近脉冲间隔)意味着当节点因崩溃或网络故障而突然离开集群时,用于处理事件的时间浪费更少,但由于事件处理器被错误地视为已断开连接而浪费时间处理事件的风险增加。 较高的值(远大于脉冲间隔)意味着当节点因崩溃或网络故障而突然离开集群时,用于处理事件的时间浪费更多,但由于事件处理器被错误地视为已断开连接而浪费时间处理事件的风险降低。 有关更多信息,请参阅参考文档的此部分。 环境变量: 显示更多 |
|
|
一次事务最多处理多少条外发事件。 较高的值将减少后台进程打开的事务数量,并可能由于一级缓存(持久化上下文)而提高性能,但会增加内存使用量,在极端情况下可能导致 有关更多信息,请参阅参考文档的此部分。 环境变量: 显示更多 |
整数 |
|
处理外发事件的事务超时时间。 当此属性未设置时,Hibernate Search 将使用 JTA 事务管理器中配置的任何默认事务超时,这可能对于批处理来说太低,并且在处理事件批次时可能导致事务超时。如果发生这种情况,请使用此属性为事件处理设置更高的事务超时。 有关更多信息,请参阅参考文档的此部分。 环境变量: 显示更多 |
||
事件处理器在上次处理失败后必须等待多长时间才能重新处理事件。 使用值 有关更多信息,请参阅参考文档的此部分。 环境变量: 显示更多 |
|
|
当主动等待事件处理器挂起自身时,轮询代理表以获取下一次查询的间隔。 较低的值会缩短大索引器代理检测到事件处理器最终挂起自身所需的时间,但在大索引器代理主动等待时会增加数据库的压力。 较高的值会增加大索引器代理检测到事件处理器最终挂起自身所需的时间,但在大索引器代理主动等待时会减少数据库的压力。 有关更多信息,请参阅 参考文档的此部分。 环境变量: 显示更多 |
|
|
大索引器在必须执行“脉冲”(更新和检查代理表中的注册)之前可以等待多长时间。 脉冲间隔必须设置为介于轮询间隔和到期间隔的三分之一(1/3)之间的值。 较低的值(接近轮询间隔)意味着在进行大索引期间,由于大索引器代理被错误地视为已断开连接,导致事件处理器再次开始处理事件而浪费的时间风险降低,但由于更频繁地更新代理表中的大索引器代理条目,数据库压力更大。 较高的值(接近到期间隔)意味着在进行大索引期间,由于大索引器代理被错误地视为已断开连接,导致事件处理器再次开始处理事件而浪费的时间风险增加,但由于不太频繁地更新代理表中的大索引器代理条目,数据库压力更小。 有关更多信息,请参阅 参考文档的此部分。 环境变量: 显示更多 |
|
|
事件处理器的“脉冲”在被视为处理器已断开连接并强制将其从集群中移除之前保持有效的时长。 到期间隔必须设置为至少是脉冲间隔的 3 倍的值。 较低的值(接近脉冲间隔)意味着在进行大索引期间,由于大索引器代理崩溃而导致事件处理器未处理事件而浪费的时间更少,但由于大索引器代理被错误地视为已断开连接,事件处理器再次开始处理事件的风险增加。 较高的值(远大于脉冲间隔)意味着在进行大索引期间,由于大索引器代理崩溃而导致事件处理器未处理事件而浪费的时间更多,但由于大索引器代理被错误地视为已断开连接,事件处理器再次开始处理事件的风险降低。 有关更多信息,请参阅 参考文档的此部分。 环境变量: 显示更多 |
|
|
类型 |
默认 |
|
类型 |
默认 |
|
代理表使用的数据库目录。 环境变量: 显示更多 |
字符串 |
|
代理表使用的模式目录。 环境变量: 显示更多 |
字符串 |
|
代理表的名称。 环境变量: 显示更多 |
字符串 |
|
代理表用于 UUID 生成器的策略。 可用策略
环境变量: 显示更多 |
|
|
用于表示外发事件表中的 UUID 的 Hibernate ORM 基本类型的名称。 请参阅 Hibernate ORM 文档的此部分 以了解可能的 UUID 表示形式。 默认为特殊值 环境变量: 显示更多 |
字符串 |
|
外发事件表使用的数据库目录。 环境变量: 显示更多 |
字符串 |
|
外发事件表使用的模式目录。 环境变量: 显示更多 |
字符串 |
|
外发事件表的名称。 环境变量: 显示更多 |
字符串 |
|
外发事件表用于 UUID 生成器的策略。 可用策略
环境变量: 显示更多 |
|
|
用于表示外发事件表中的 UUID 的 Hibernate ORM 基本类型的名称。 请参阅 Hibernate ORM 文档的此部分 以了解可能的 UUID 表示形式。 默认为特殊值 环境变量: 显示更多 |
字符串 |
|
类型 |
默认 |
|
事件处理器是否已启用,即事件是否将被处理以在此应用程序实例上执行自动重新索引。 这可以设置为 有关更多信息,请参阅参考文档的此部分。 环境变量: 显示更多 |
布尔值 |
|
将构成实体更改事件处理分区的分片总数。 默认情况下,分片是动态的,因此不需要设置此属性。 如果您想明确控制分片的数量和分配,则必须配置静态分片,然后设置此属性以及分配的分片(请参阅 有关事件处理器分片的更多信息,请参阅参考文档的此部分。 环境变量: 显示更多 |
整数 |
|
在将构成实体变更事件分区的分片中,由此应用程序实例处理的分片。 默认情况下,分片是动态的,因此不需要设置此属性。 如果您想显式控制分片的数量和分配,则必须配置静态分片,然后设置此属性以及总分片数是必需的。 分片通过范围 有关事件处理器分片的更多信息,请参阅参考文档的此部分。 环境变量: 显示更多 |
int 列表 |
|
在查询外发事件表没有返回任何事件后,等待下一次查询的间隔。 较低的值会缩短变更反映在索引中的时间,但会在没有新事件时增加数据库的压力。 有关更多信息,请参阅参考文档的此部分。 环境变量: 显示更多 |
|
|
事件处理器在必须执行“脉冲”(更新和检查代理表中的注册)之前可以轮询事件的时间。 脉冲间隔必须设置为介于轮询间隔和到期间隔的三分之一(1/3)之间的值。 较低的值(接近轮询间隔)意味着当节点加入或离开集群时,浪费的时间更少,并且因为事件处理器被错误地视为已断开连接而浪费时间处理事件的风险降低,但由于更频繁地检查代理列表,数据库压力更大。 较高的值(接近到期间隔)意味着当节点加入或离开集群时,浪费的时间更多,并且因为事件处理器被错误地视为已断开连接而浪费时间处理事件的风险增加,但由于不太频繁地检查代理列表,数据库压力更小。 有关更多信息,请参阅参考文档的此部分。 环境变量: 显示更多 |
|
|
事件处理器的“脉冲”在被视为处理器已断开连接并强制将其从集群中移除之前保持有效的时长。 到期间隔必须设置为至少是脉冲间隔的 3 倍的值。 较低的值(接近脉冲间隔)意味着当节点因崩溃或网络故障而突然离开集群时,用于处理事件的时间浪费更少,但由于事件处理器被错误地视为已断开连接而浪费时间处理事件的风险增加。 较高的值(远大于脉冲间隔)意味着当节点因崩溃或网络故障而突然离开集群时,用于处理事件的时间浪费更多,但由于事件处理器被错误地视为已断开连接而浪费时间处理事件的风险降低。 有关更多信息,请参阅参考文档的此部分。 环境变量: 显示更多 |
|
|
一次事务最多处理多少条外发事件。 较高的值将减少后台进程打开的事务数量,并可能由于一级缓存(持久化上下文)而提高性能,但会增加内存使用量,在极端情况下可能导致 有关更多信息,请参阅参考文档的此部分。 环境变量: 显示更多 |
整数 |
|
处理外发事件的事务超时时间。 当此属性未设置时,Hibernate Search 将使用 JTA 事务管理器中配置的任何默认事务超时,这可能对于批处理来说太低,并且在处理事件批次时可能导致事务超时。如果发生这种情况,请使用此属性为事件处理设置更高的事务超时。 有关更多信息,请参阅参考文档的此部分。 环境变量: 显示更多 |
||
事件处理器在上次处理失败后必须等待多长时间才能重新处理事件。 使用值 有关更多信息,请参阅参考文档的此部分。 环境变量: 显示更多 |
|
|
当主动等待事件处理器挂起自身时,轮询代理表以获取下一次查询的间隔。 较低的值会缩短大索引器代理检测到事件处理器最终挂起自身所需的时间,但在大索引器代理主动等待时会增加数据库的压力。 较高的值会增加大索引器代理检测到事件处理器最终挂起自身所需的时间,但在大索引器代理主动等待时会减少数据库的压力。 有关更多信息,请参阅 参考文档的此部分。 环境变量: 显示更多 |
|
|
大索引器在必须执行“脉冲”(更新和检查代理表中的注册)之前可以等待多长时间。 脉冲间隔必须设置为介于轮询间隔和到期间隔的三分之一(1/3)之间的值。 较低的值(接近轮询间隔)意味着在进行大索引期间,由于大索引器代理被错误地视为已断开连接,导致事件处理器再次开始处理事件而浪费的时间风险降低,但由于更频繁地更新代理表中的大索引器代理条目,数据库压力更大。 较高的值(接近到期间隔)意味着在进行大索引期间,由于大索引器代理被错误地视为已断开连接,导致事件处理器再次开始处理事件而浪费的时间风险增加,但由于不太频繁地更新代理表中的大索引器代理条目,数据库压力更小。 有关更多信息,请参阅 参考文档的此部分。 环境变量: 显示更多 |
|
|
事件处理器的“脉冲”在被视为处理器已断开连接并强制将其从集群中移除之前保持有效的时长。 到期间隔必须设置为至少是脉冲间隔的 3 倍的值。 较低的值(接近脉冲间隔)意味着在进行大索引期间,由于大索引器代理崩溃而导致事件处理器未处理事件而浪费的时间更少,但由于大索引器代理被错误地视为已断开连接,事件处理器再次开始处理事件的风险增加。 较高的值(远大于脉冲间隔)意味着在进行大索引期间,由于大索引器代理崩溃而导致事件处理器未处理事件而浪费的时间更多,但由于大索引器代理被错误地视为已断开连接,事件处理器再次开始处理事件的风险降低。 有关更多信息,请参阅 参考文档的此部分。 环境变量: 显示更多 |
|
关于 Duration 格式
要编写持续时间值,请使用标准的 您还可以使用简化的格式,以数字开头
在其他情况下,简化格式将被转换为
|