The English version of quarkus.io is the official project site. Translated sites are community supported on a best-effort basis.
このページを編集

Elasticsearch/OpenSearch を使用する Standalone モードでの Hibernate Search の使用

Quarkus アプリケーションをお持ちですか? フル機能のフルテキスト検索をユーザーに提供したいとお考えですか? このガイドでは、最適な方法を提供しています。

このガイドでは、Hibernate Search を使用して、エンティティーを Elasticsearch または OpenSearch クラスターに瞬時に同期させる方法を説明します。 また、Hibernate Search API を使用して Elasticsearch または OpenSearch クラスターにクエリーを実行する方法についても説明します。

Hibernate ORM エンティティーのインデックスを作成したい場合は、 代わりに、こちらの専用ガイド を参照してください。

要件

このガイドを完成させるには、以下が必要です:

  • ざっと 20 minutes

  • IDE

  • JDK 17+がインストールされ、 JAVA_HOME が適切に設定されていること

  • Apache Maven 3.9.9

  • 動作するコンテナランタイム(Docker, Podman)

  • 使用したい場合は、 Quarkus CLI

  • ネイティブ実行可能ファイルをビルドしたい場合、MandrelまたはGraalVM(あるいはネイティブなコンテナビルドを使用する場合はDocker)をインストールし、 適切に設定していること

アーキテクチャー

このガイドに記載されているアプリケーションにより、(シンプルな) ライブラリーを管理することができます。ユーザーは、author と book を管理するだけです。

エンティティーは Elasticsearch クラスターに保存され、インデックスが作成されます。

ソリューション

次の章で紹介する手順に沿って、ステップを踏んでアプリケーションを作成することを推奨します。 ただし、完成した例にそのまま進むこともできます。

Clone the Git repository: git clone https://github.com/quarkusio/quarkus-quickstarts.git, or download an archive.

ソリューションは、hibernate-search-standalone-elasticsearch-quickstart ディレクトリー にあります。

提供されるソリューションには、テストやテストのインフラストラクチャーなど、いくつかの追加要素が含まれています。

Maven プロジェクトの作成

まず、新しいプロジェクトが必要です。以下のコマンドで新規プロジェクトを作成します。

コマンドラインインタフェース
quarkus create app org.acme:hibernate-search-standalone-elasticsearch-quickstart \
    --extension='hibernate-search-standalone-elasticsearch,rest-jackson' \
    --no-code
cd hibernate-search-standalone-elasticsearch-quickstart

Gradleプロジェクトを作成するには、 --gradle または --gradle-kotlin-dsl オプションを追加します。

Quarkus CLIのインストールと使用方法の詳細については、 Quarkus CLI ガイドを参照してください。

Maven
mvn io.quarkus.platform:quarkus-maven-plugin:3.17.3:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=hibernate-search-standalone-elasticsearch-quickstart \
    -Dextensions='hibernate-search-standalone-elasticsearch,rest-jackson' \
    -DnoCode
cd hibernate-search-standalone-elasticsearch-quickstart

Gradleプロジェクトを作成するには、 -DbuildTool=gradle または -DbuildTool=gradle-kotlin-dsl オプションを追加します。

Windowsユーザーの場合:

  • cmdを使用する場合、(バックスラッシュ \ を使用せず、すべてを同じ行に書かないでください)。

  • Powershellを使用する場合は、 -D パラメータを二重引用符で囲んでください。例: "-DprojectArtifactId=hibernate-search-standalone-elasticsearch-quickstart"

このコマンドは、以下のエクステンションをインポートするMaven構造体を生成します:

  • Hibernate Search Standalone + Elasticsearch

  • Quarkus REST (旧称 RESTEasy Reactive) と Jackson

すでにQuarkusプロジェクトが設定されている場合は、プロジェクトのベースディレクトリーで以下のコマンドを実行することで、 プロジェクトに hibernate-search-standalone-elasticsearch エクステンションを追加できます。

コマンドラインインタフェース
quarkus extension add hibernate-search-standalone-elasticsearch
Maven
./mvnw quarkus:add-extension -Dextensions='hibernate-search-standalone-elasticsearch'
Gradle
./gradlew addExtension --extensions='hibernate-search-standalone-elasticsearch'

これにより、 pom.xml に以下が追加されます:

pom.xml
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-hibernate-search-standalone-elasticsearch</artifactId>
</dependency>
build.gradle
implementation("io.quarkus:quarkus-hibernate-search-standalone-elasticsearch")

ベアクラスの作成

まず、model サブパッケージに Book クラスと Author クラスを作成します。

package org.acme.hibernate.search.elasticsearch.model;

import java.util.List;
import java.util.Objects;

public class Author {

    public UUID id; (1)

    public String firstName;

    public String lastName;

    public List<Book> books;

    public Author(UUID id, String firstName, String lastName, List<Book> books) {
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
        this.books = books;
    }
}
1 ここではパブリックフィールドを使用しています。 なぜなら、より短く、本質的にデータクラスであるものに対してカプセル化が期待されていないからです。

ただし、getter/setter 付きのプライベートフィールドを使用する場合は、 getter/setter が JavaBeans の命名規則に従っている限りは、まったく問題はなく、完璧に動作します (getSomething()/isSomething()/setSomething(…​))。

package org.acme.hibernate.search.elasticsearch.model;

import java.util.Objects;

public class Book {

    public UUID id;

    public String title;

    public Book(UUID id, String title) {
        this.id = id;
        this.title = title;
    }
}

Hibernate Searchアノテーションの使用

クラスのフルテキスト検索機能の有効化は、アノテーションいくつか追加する場合と同様に、簡単にできます。

この内容を含めるように Author エンティティーを編集してみましょう。

package org.acme.hibernate.search.elasticsearch.model;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.UUID;

import org.hibernate.search.engine.backend.types.Sortable;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.DocumentId;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.FullTextField;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.IdProjection;
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 org.hibernate.search.mapper.pojo.mapping.definition.annotation.ProjectionConstructor;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.SearchEntity;

@SearchEntity (1)
@Indexed (2)
public class Author {

    @DocumentId (3)
    public UUID id;

    @FullTextField(analyzer = "name") (4)
    @KeywordField(name = "firstName_sort", sortable = Sortable.YES, normalizer = "sort") (5)
    public String firstName;

    @FullTextField(analyzer = "name")
    @KeywordField(name = "lastName_sort", sortable = Sortable.YES, normalizer = "sort")
    public String lastName;

    @IndexedEmbedded (6)
    public List<Book> books = new ArrayList<>();

    public Author(UUID id, String firstName, String lastName) {
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
    }

    @ProjectionConstructor (7)
    public Author(@IdProjection UUID id, String firstName, String lastName, List<Book> books) {
        this( id, firstName, lastName );
        this.books = books;
    }
}
1 まず、Author タイプを エンティティータイプ とマークします。 つまり、これは Author タイプが独自のライフサイクル (他のタイプに結びついていない) を持ち、 すべての `BookAuthor インスタンスはイミュータブルな一意の識別子を持つことを意味します。
2 次に、@Indexed アノテーションを使用して、Author エンティティーをフルテキストインデックスの一部として登録します。
3 続いて、ドキュメント識別子を定義し、必須設定を終了します。
4 @FullTextField アノテーションは、フルテキスト検索用に特別に調整されたインデックスのフィールドを宣言します。 特に、トークン (~ 単語) を分割して分析するためのアナライザーを定義する必要があります。 - これについては後で説明します。
5 このように、同じプロパティーに複数のフィールドを定義することができます。 ここでは、固有の名前を持つ @KeywordField を定義しています。 主な違いは、キーワードフィールドはトークン化されません (文字列は 1 つのトークンとして保持)が、正規化 (すなわちフィルタリング) できるという点です。これについては後で説明します。 このフィールドは author のソートに使用することを意図しているため、ソート可能とマークされています。
6 @IndexedEmbedded の目的は、Book フィールドを Author インデックスに含めることです。 この場合は、デフォルトの設定を使用します。つまり、関連付けられている Book インスタンスのすべてのフィールド (つまり title フィールド) がインデックスに含まれます。 @IndexedEmbedded はネストされたドキュメントもサポート (structure = NESTED 属性を使用) しますが、ここでは必要ありません。 また、すべてのフィールドを親インデックスに含める必要がない場合は、includePaths/excludePaths 属性を使用して含めるフィールドを指定することができます。
7 (単一の) コンストラクターを @ProjectionConstructor としてマークします。 これにより、インデックスの内容から Author インスタンスを再構築できるようにします。

author のインデックスが作成されたので、この @IndexedEmbedded アノテーションが 実際に 何か を含むように、book をマッピングします。

Book クラスを開き、以下の内容を含めます。

package org.acme.hibernate.search.elasticsearch.model;

import java.util.Objects;
import java.util.UUID;

import org.hibernate.search.mapper.pojo.mapping.definition.annotation.FullTextField;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.KeywordField;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.ProjectionConstructor;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.SearchEntity;

@SearchEntity (1)
public class Book {

    @KeywordField (2)
    public UUID id;

    @FullTextField(analyzer = "english") (3)
    public String title;

    @ProjectionConstructor (4)
    public Book(UUID id, String title) {
        this.id = id;
        this.title = title;
    }
}
1 また、Book タイプを エンティティータイプ としてマークします。 しかし、book 専用のインデックスは必要ないと判断したため、@Indexed は使用しません。
2 book の ID のインデックスを作成して、ID が表示されるようにします (以下を参照)。
3 Author の場合と同様に @FullTextField を使用しますが、アナライザーが異なることに気付くでしょう。これについては後で詳しく説明します。
4 Author`と同様に、コンストラクターを@ProjectionConstructor`としてマークします。 これにより、インデックスの内容から Book インスタンスを再構築できるようにします。

アナライザーとノーマライザー

はじめに

分析はフルテキスト検索の大きな部分を占めています。インデックス作成や検索クエリー構築の際に、テキストがどのように処理されるかを定義します。

アナライザーの役割は、テキストをトークン (~ 単語) に分割し、フィルターをかけることです (例: すべてを小文字にしたり、アクセントを削除したりなど)。

ノーマライザーは入力を 1 つのトークンとして保持する特殊なアナライザーです。 特に、キーワードのソートやインデックス作成に有効です。

多くのバンドルされたアナライザーがありますが、自分の目的に合わせて独自に開発することもできます。

Elasticsearch 分析フレームワークの詳細は、https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis.html[Elasticsearch ドキュメントの分析セクション] を参照してください。

使用するアナライザーの定義

エンティティーに Hibernate Search アノテーションを追加した際に、使用するアナライザーとノーマライザーを定義しました。 通常は、以下のようになります。

@FullTextField(analyzer = "english")
@FullTextField(analyzer = "name")
@KeywordField(name = "lastName_sort", sortable = Sortable.YES, normalizer = "sort")

以下を使用しています。

  • 人名用の name というアナライザー

  • book タイトル用の 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.standalone.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 Configurer の実装に @SearchExtension 修飾子のアノテーションを付けて、 すべての Elasticsearch インデックスに対して (デフォルトで) Hibernate Search Standalone で使用するように Quarkus に指示します。

アノテーションは、特定の永続ユニット (@SearchExtension(persistenceUnit = "nameOfYourPU"))、 バックエンド (@SearchExtension(backend = "nameOfYourBackend"))、インデックス (@SearchExtension(index = "nameOfYourIndex"))、 またはそれらの組み合わせ (@SearchExtension(persistenceUnit = "nameOfYourPU", backend = "nameOfYourBackend", index = "nameOfYourIndex")) をターゲットにすることもできます。

2 これは、スペースで単語を分離し、ASCII 以外の文字をそれに対応する ASCII 文字に置き換えて (つまり、アクセントを除去)、すべてを小文字にするシンプルなアナライザーです。 これは、例では author 名に使用されています。
3 これはもう少し積極的で、ステミングも含まれています。作成されたインデックスの入力に mysteries が含まれていても、mystery を検索して結果を得ることができます。 人名に対しては確かに無理がありますが、book のタイトルに関しては完璧です。
4 ここではソートに使われるノーマライザーを紹介します。最初のアナライザーと非常によく似ていますが、1つだけのトークンが欲しいので、単語をトークン化しないことを除けば同じです。

アナライザーの設定の詳細は、 参照ドキュメントのこちらのセクション を参照してください。

REST サービスの実装

org.acme.hibernate.search.elasticsearch.LibraryResource クラスを作成します:

package org.acme.hibernate.search.elasticsearch;

import java.util.ArrayList;
import java.util.UUID;

import jakarta.inject.Inject;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.NotFoundException;
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.pojo.standalone.mapping.SearchMapping;
import org.hibernate.search.mapper.pojo.standalone.session.SearchSession;

import org.jboss.resteasy.reactive.RestForm;
import org.jboss.resteasy.reactive.RestPath;

@Path("/library")
public class LibraryResource {

    @Inject
    SearchMapping searchMapping; (1)

    @PUT
    @Path("author")
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    public void addAuthor(@RestForm String firstName, @RestForm String lastName) {
        try (var searchSession = searchMapping.createSession()) { (2)
            Author author = new Author(UUID.randomUUID(), firstName, lastName, new ArrayList<>());
            searchSession.indexingPlan().add(author); (3)
        }
    }

    @GET
    @Path("author/{id}")
    public Author getAuthor(@RestPath UUID id) {
        try (var searchSession = searchMapping.createSession()) {
            return getAuthor(searchSession, id);
        }
    }

    private Author getAuthor(SearchSession searchSession, UUID id) {
        return searchSession.search(Author.class) (4)
                .where(f -> f.id().matching(id))
                .fetchSingleHit()
                .orElseThrow(NotFoundException::new);
    }

    @POST
    @Path("author/{id}")
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    public void updateAuthor(@RestPath UUID id, @RestForm String firstName, @RestForm String lastName) {
        try (var searchSession = searchMapping.createSession()) {
            Author author = getAuthor(searchSession, id); (5)
            author.firstName = firstName;
            author.lastName = lastName;
            searchSession.indexingPlan().addOrUpdate(author); (5)
        }
    }

    @DELETE
    @Path("author/{id}")
    public void deleteAuthor(@RestPath UUID id) {
        try (var searchSession = searchMapping.createSession()) {
            searchSession.indexingPlan().purge(Author.class, id, null); (6)
        }
    }

    @PUT
    @Path("author/{authorId}/book/")
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    public void addBook(@RestPath UUID authorId, @RestForm String title) {
        try (var searchSession = searchMapping.createSession()) {
            Author author = getAuthor(searchSession, authorId); (7)
            author.books.add(new Book(authorId, title));
            searchSession.indexingPlan().addOrUpdate(author);
        }
    }

    @DELETE
    @Path("author/{authorId}/book/{bookId}")
    public void deleteBook(@RestPath UUID authorId, @RestPath UUID bookId) {
        try (var searchSession = searchMapping.createSession()) {
            Author author = getAuthor(searchSession, authorId); (7)
            author.books.removeIf(book -> book.id.equals(bookId));
            searchSession.indexingPlan().addOrUpdate(author);
        }
    }
}
1 Hibernate Search API へのメインエントリーポイントである Hibernate Search マッピングを注入します。
2 インデックスに対する操作を実行できる Hibernate Search セッションを作成します。
3 新しい Authorのインデックスを作成するには、セッションのインデックスプランを取得し、author のインスタンスを引数に渡して add を呼び出します。
4 インデックスから Author を取得するには、識別子による簡単な検索 を実行します (検索については後ほど詳しく説明します)。
5 Author を更新するには、インデックスから Author を取得し、変更を適用し、 セッションのインデックスプランを取得して、author インスタンスを引数に渡して addOrUpdate を呼び出します。
6 識別子で Author を削除するには、セッションのインデックスプランを取得し、 author クラスと識別子を引数に渡して purge を呼び出します。
7 book は author によって "所有" されるため ( author ごとに複製され、そのライフサイクルは author のライフサイクルにバインドされます)、 book の追加/削除は、単なる author への更新になります。

画期的なことは何もありません。REST サービスで CRUD 操作をいくつか行うだけ、 その際に、Hibernate Search API を使用します。

興味深いのは、検索エンドポイントが追加された点です。 LibraryResource では、次のメソッド (およびいくつかの import) を追加する必要があるだけです。

    @GET
    @Path("author/search")
    public List<Author> searchAuthors(@RestQuery String pattern, (1)
            @RestQuery Optional<Integer> size) {
        try (var searchSession = searchMapping.createSession()) { (2)
            return searchSession.search(Author.class) (3)
                    .where(f -> pattern == null || pattern.isBlank()
                            ? 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 パラメーター名の繰り返しを避けるために org.jboss.resteasy.annotations.jaxrs.QueryParam アノテーションを使用します。
2 インデックスに対する操作を実行できる Hibernate Search セッションを作成します。
3 Author を検索していることを示しています。
4 述語を作成します。パターンが空の場合は matchAll() 述語を使用します。
5 有効なパターンがあれば、パターンにマッチする firstNamelastNamebooks.title フィールドに対する simpleQueryString() 述語を作成します。
6 結果のソート順を定義します。ここでは、姓でソートし、次に名でソートしています。ソートには作成した特定のフィールドを使用していることに注意してください。
7 size で指定した数の一致度が高いものをフェッチします。デフォルトでは 20 です。もちろんページングもサポートしています。

Hibernate Search DSLは Elasticsearch の述語 (match、range、nested、phrase、spatial…​) の重要なサブセットをサポートしています。 オートコンプリートを使って DSL をご自由にお試しください。

それでも十分でない場合は、いつでも JSONを直接使う述語の定義 にフォールバックできます。

データの自動初期化

このデモの目的のために、初期データセットをインポートしてみましょう。

LibraryResource にいくつかのメソッドを追加してみましょう。

    void onStart(@Observes StartupEvent ev) { (1)
        // Index some test data if nothing exists
        try (var searchSession = searchMapping.createSession()) {
            if (0 < searchSession.search(Author.class) (2)
                    .where(f -> f.matchAll())
                    .fetchTotalHitCount()) {
                return;
            }
            for (Author author : initialDataSet()) { (3)
                searchSession.indexingPlan().add(author); (4)
            }
        }
    }

    private List<Author> initialDataSet() {
        return List.of(
                new Author(UUID.randomUUID(), "John", "Irving",
                        List.of(
                                new Book(UUID.randomUUID(), "The World According to Garp"),
                                new Book(UUID.randomUUID(), "The Hotel New Hampshire"),
                                new Book(UUID.randomUUID(), "The Cider House Rules"),
                                new Book(UUID.randomUUID(), "A Prayer for Owen Meany"),
                                new Book(UUID.randomUUID(), "Last Night in Twisted River"),
                                new Book(UUID.randomUUID(), "In One Person"),
                                new Book(UUID.randomUUID(), "Avenue of Mysteries"))),
                new Author(UUID.randomUUID(), "Paul", "Auster",
                        List.of(
                                new Book(UUID.randomUUID(), "The New York Trilogy"),
                                new Book(UUID.randomUUID(), "Mr. Vertigo"),
                                new Book(UUID.randomUUID(), "The Brooklyn Follies"),
                                new Book(UUID.randomUUID(), "Invisible"),
                                new Book(UUID.randomUUID(), "Sunset Park"),
                                new Book(UUID.randomUUID(), "4 3 2 1"))));
    }
1 アプリケーションの起動時に実行されるメソッドを追加します。
2 インデックスにすでにデータがあるか確認します。ない場合は終了します。
3 初期データセットを生成します。
4 author ごとに、これをインデックスに追加します。

アプリケーションの設定

いつものように、Quarkusの設定ファイル( application.properties )ですべての設定を行うことができます。

以下の内容の src/main/resources/import.sql ファイルを作成してみましょう:

quarkus.hibernate-search-standalone.mapping.structure=document (1)
quarkus.hibernate-search-standalone.elasticsearch.version=8 (2)
quarkus.hibernate-search-standalone.indexing.plan.synchronization.strategy=sync (3)

%prod.quarkus.hibernate-search-standalone.elasticsearch.hosts=localhost:9200 (4)
1 Hibernate Search にエンティティーの構造を伝える必要があります。

このアプリケーションでは、インデックスが作成されたエンティティー (author) が "ドキュメント" のルートであるとみなされます。 author は、関連性を通じて参照する book を "所有” します。 つまり、author のみを更新することは できません

その他のオプションと詳細は、quarkus.hibernate-search-standalone.mapping.structure を参照してください。

2 使用する Elasticsearch のバージョンを Hibernate Search に伝える必要があります。

Elasticsearch のマッピング構文はバージョンによって大きく異なるため、これは重要です。 起動時間を短縮するためにマッピングはビルド時に作成されるため、Hibernate Search はクラスターに接続して自動的にバージョンを検出することができません。 OpenSearch の場合、バージョンの前に opensearch: を付ける必要がある点に注意してください。OpenSearch 互換性 を参照してください。

3 これは、エンティティーが検索可能になるのを待ってから書き込みが完了したとみなすことを意味します。 実稼働環境では、デフォルトの write-sync の方がパフォーマンスが高くなります。 テスト時には、エンティティーがすぐに検索可能になる必要があるため、sync を使用することが特に重要です。
4 開発とテストの場合は、Dev Services に依存します。 つまり、Quarkus は Elasticsearch クラスターを自動的に起動します。 しかし、実稼働モードの場合は、 Elasticsearch クラスターを手動で起動したいと考えています。 そのため、prod プロファイルで Quarkus にこの接続情報を提供します (%prod. 接頭辞)。

Dev Services に依存していることから、Elasticsearch スキーマは、 (quarkus.hibernate-search-standalone.schema-management.strategy が明示的に設定されていない限り) テストと開発モードで アプリケーションの起動ごとに自動的に削除され、再作成されます。

何らかの理由で Dev Services を利用できない場合は、 以下のプロパティーを設定することで、同様の動作をさせることができます。

%dev,test.quarkus.hibernate-search-standalone.schema-management.strategy=drop-and-create
Hibernate Search Standalone エクステンションの設定に関する詳細は、Configuration Reference を参照してください。

フロントエンドの作成

それでは、LibraryResource と対話するための簡単なWebページを追加してみましょう。 Quarkus は、META-INF/resources ディレクトリの下にある静的リソースを自動的に提供します。 src/main/resources/META-INF/resources ディレクトリーで、既存の index.html ファイルを、この index.html ファイルの内容で上書きしてください。

アプリケーションの使用

これで、REST サービスと対話できるようになりました。

  • Quarkus アプリケーションを次のように起動します。

    CLI
    quarkus dev
    Maven
    ./mvnw quarkus:dev
    Gradle
    ./gradlew --console=plain quarkusDev
  • ブラウザーで http://localhost:8080/ を開きます。

  • author または book タイトルを検索します (一部のデータは初期化されています)。

  • 新しい author や book を作成し、それらを検索することもできます

ご覧のように、すべての更新が自動的に Elasticsearch クラスターに同期されます。

ネイティブ実行可能ファイルのビルド

以下のコマンドでネイティブの実行可能ファイルをビルドすることができます。

コマンドラインインタフェース
quarkus build --native
Maven
./mvnw install -Dnative
Gradle
./gradlew build -Dquarkus.native.enabled=true

ネイティブ実行可能ファイルのコンパイルと同様に、この操作は大量のメモリーを消費します。

ネイティブ実行可能ファイルをビルドしている間は 2 つのコンテナーを停止して、ビルドが終わったら再度起動した方が安全かもしれません。

この実行は、./target/hibernate-search-standalone-elasticsearch-quickstart-1.0.0-SNAPSHOT-runner の実行と同じくらい簡単です。

その後、ブラウザーで http://localhost:8080/ を開き、アプリケーションを使用します。

起動は通常より少し遅くなります。これは主に、起動時に毎回 Elasticsearch マッピングを削除して再作成するためです。 いくつかの初期データのインデックスも作成します。

実際のアプリケーションでは、これは明らかに、起動時に毎回行うものではありません。

開発サービス (設定不要のデータストア)

Quarkus は、設定なしでさまざまなコンテナーを起動できる 開発サービス と呼ばれる機能をサポートしています。

Elasticsearch の場合、このサポートはデフォルトの Elasticsearch 接続にも及んでいます。 つまり、quarkus.hibernate-search-standalone.elasticsearch.hosts を設定していない場合は、 Quarkus はテストの実行時または dev モード で Elasticsearch コンテナーを自動的に起動し、 接続を自動的に設定します。

アプリケーションの実稼働バージョンを実行する場合、Elasticsearch 接続は通常通り設定する必要があります。 したがって、application.properties に実稼働バージョンのデータベース設定を含め、Dev Services を引き続き使用したい場合は、 %prod. プロファイルを使用して、Elasticsearch 設定を定義することを推奨します。

Dev Services for Elasticsearch は現時点では複数のクラスターを同時に起動することができず、デフォルトの永続化ユニットのデフォルトのバックエンドでのみ動作します。名前付き永続化ユニットや名前付きバックエンドは Dev Services for Elasticsearch を利用することができません。

詳細については、 Dev Services for Elasticsearch ガイド をご覧ください。

プログラムによるマッピング

何らかの理由で Hibernate Search アノテーションをエンティティーに追加できない場合は、 代わりにプログラムでマッピングを適用することができます。 プログラムによるマッピングは、ProgrammaticMappingConfigurationContext を通じて設定され、 マッピング Configurer (HibernateOrmSearchMappingConfigurer) を介して公開されます。

マッピング Configurer (StandalonePojoMappingConfigurer) を使用すると、単なるプログラムによるマッピング機能以上のものを実現できます。 アノテーションマッピング、ブリッジなどの設定 も実現されます。

以下は、プログラムによるマッピングを適用するマッピング Configurer の例です。

package org.acme.hibernate.search.elasticsearch.config;

import org.hibernate.search.mapper.pojo.standalone.mapping.StandalonePojoMappingConfigurationContext;
import org.hibernate.search.mapper.pojo.standalone.mapping.StandalonePojoMappingConfigurer;
import org.hibernate.search.mapper.pojo.mapping.definition.programmatic.TypeMappingStep;

import io.quarkus.hibernate.search.standalone.elasticsearch.SearchExtension;

@SearchExtension (1)
public class CustomMappingConfigurer implements StandalonePojoMappingConfigurer {

	@Override
    public void configure(StandalonePojoMappingConfigurationContext context) {
        TypeMappingStep type = context.programmaticMapping()    (2)
                .type(SomeIndexedEntity.class);                 (3)
        type.searchEntity();                                    (4)
        type.indexed()                                          (5)
                .index(SomeIndexedEntity.INDEX_NAME);           (6)
        type.property("id").documentId();                       (7)
        type.property("text").fullTextField();                  (8)
    }
}
1 Configurer の実装に @SearchExtension 修飾子のアノテーションを付けて、 Hibernate Search Standalone で使用するように Quarkus に指示します。
2 プログラムによるマッピングコンテキストにアクセスします。
3 SomeIndexedEntity タイプのマッピングステップを作成します。
4 Hibernate Search のエンティティータイプとして SomeIndexedEntity を定義します。
5 SomeIndexedEntity エンティティーをインデックスが作成されたと定義します。
6 SomeIndexedEntity エンティティーに使用するインデックス名を指定します。
7 ドキュメント ID プロパティーを定義します。
8 text プロパティーのフルテキスト検索フィールドを定義します。

OpenSearch 互換性

Hibernate Search は ElasticsearchOpenSearch の両方に対応していますが、デフォルトでは Elasticsearch クラスターとの連携を前提としています。

代わりに Hibernate Search を OpenSearch クラスターで動作させるには、 設定されたバージョンに`opensearch:`を接頭辞として付けます。 以下に例を示します。

quarkus.hibernate-search-standalone.elasticsearch.version=opensearch:2.16

その他の設定オプションや API は、Elasticsearch の場合とまったく同じです。

Elasticsearch の互換性のあるディストリビューションとバージョンの詳細は、 Hibernate Search の参照ドキュメントのこちらのセクション を参照してください。

CDI インテグレーション

エントリーポイントの注入

CDI を使用して、Hibernate Search のメインエントリーポイントである SearchMapping を注入できます。

@Inject
SearchMapping searchMapping;

カスタムコンポーネントのプラグイン

Hibernate Search Standalone の Quarkus エクステンションは自動的に @SearchExtension アノテーションが付けられたコンポーネントを Hibernate Search に注入します。

アノテーションは、注入されるコンポーネントのタイプに適している場合に、 オプションで特定の バックエンド (@SearchExtension(backend = "nameOfYourBackend"))、インデックス (@SearchExtension(index = "nameOfYourIndex"))、 またはそれらの組み合わせ (@SearchExtension(backend = "nameOfYourBackend", index = "nameOfYourIndex")) をターゲットにできます。

この機能は、次のコンポーネントタイプで使用できます。

org.hibernate.search.engine.reporting.FailureHandler

バックグラウンドプロセスで発生した障害が通知されるコンポーネント (主にインデックス操作)。

スコープ: アプリケーションごとに 1 つ。

詳細は、参照ドキュメントのこちらのセクション を参照してください。

org.hibernate.search.mapper.pojo.standalone.mapping.StandalonePojoMappingConfigurer

特にプログラムによって Hibernate Search マッピングを設定するために使用されるコンポーネント。

スコープ: 永続性ユニットごとに 1 つ以上。

詳細は、this section of this guide を参照してください。

org.hibernate.search.mapper.pojo.work.IndexingPlanSynchronizationStrategy

アプリケーションスレッドとインデックスの作成を同期する方法を設定するために使用されるコンポーネント。

スコープ: アプリケーションごとに 1 つ。

quarkus.hibernate-search-standalone.indexing.plan.synchronization.strategy を介して組み込み実装に設定することもできます。

詳細は、参照ドキュメントのこちらのセクション を参照してください。

org.hibernate.search.backend.elasticsearch.analysis.ElasticsearchAnalysisConfigurer

フルテキスト分析 (アナライザー、ノーマライザーなど) を設定するために使用されるコンポーネント。

スコープ: バックエンドごとに 1 つ以上。

詳細は、this section of this guide を参照してください。

org.hibernate.search.backend.elasticsearch.index.layout.IndexLayoutStrategy

Elasticsearch レイアウト (インデックス名、インデックスエイリアスなど) を設定するために使用されるコンポーネント。

スコープ: バックエンドごとに 1 つ。

quarkus.hibernate-search-standalone.elasticsearch.layout.strategy を介して組み込み実装に設定することもできます。

詳細は、参照ドキュメントのこちらのセクション を参照してください。

オフライン起動

デフォルトでは、Hibernate Search は起動時に Elasticsearch クラスターにいくつかのリクエストを送信します。 Hibernate Search の起動時に Elasticsearch クラスターが稼働していない場合は、 起動失敗の原因となります。

これに対処するためには起動時にリクエストを送信しないようにHibernate Searchを設定します:

もちろん、この構成でも、Elasticsearch クラスターにアクセスできるようになるまでは、 Hibernate Search はインデックスを作成したり、検索クエリーを実行したりすることはできません。

quarkus.hibernate-search-standalone.schema-management.strategynone に設定してスキーマの自動作成を無効にした場合、 アプリケーションが、エンティティーの永続化/更新や検索リクエストの実行を開始する前に、 手動でスキーマを作成する必要があります。

詳細は、参照ドキュメントのこちらのセクション を参照してください。

ロード中

Elasticsearch をプライマリーデータストアとして使用する代わりとして、 このエクステンションは、別のデータストアから取得したエンティティーのインデックスを作成するためにも使用できます。

このようなシナリオでは、 quarkus.hibernate-search-standalone.mapping.structure を プライマリーデータストアの構造に一致する値に設定する必要があります。

これを実行するには、エンティティーを他のデータストアからロードする必要があります。 このようなロードは、明示的に実装する必要があります。

ロードの設定に関する詳細は、Hibernate Search のリファレンスドキュメントを参照してください。

Quarkus では、Hibernate Search の参照ドキュメントに記載されているエンティティーローダーは、 CDI bean のように定義できますが、 @SearchEntity(loadingBinder = …​) を使用して特定のエンティティーにアタッチする必要があります。

管理エンドポイント

Hibernate Search の管理エンドポイントは、プレビュー機能とされています。

プレビュー版 では、後方互換性やエコシステムでの存在は保証されていません。 具体的な改善のためには、設定や API、あるいはストレージのフォーマットを変更する必要があるかもしれませんが、 安定化 に向けた計画は進行中です。 ご意見およびご感想は、https://groups.google.com/d/forum/quarkus-dev[メーリングリスト] や GitHub の issue トラッカー までお寄せください。

Hibernate Search エクステンションは、管理インターフェイス を通じてデータを再インデックスするための HTTP エンドポイントを提供します。 デフォルトでは、このエンドポイントは使用できません。以下に示すように、設定プロパティーを通じて有効にできます。

quarkus.management.enabled=true (1)
quarkus.hibernate-search-standalone.management.enabled=true (2)
1 管理インターフェイス を有効にします。
2 Hibernate Search Standalone 固有の管理エンドポイントを有効にします。

管理エンドポイントが有効になると、/q/hibernate-search/standalone/reindex 経由でデータのインデックスの再作成が可能になります。ここで、/q はデフォルトの管理ルートパスで、 /hibernate-search/standalone/ はデフォルトの Hibernate Search ルート管理パスになります。 以下に示すように、(/hibernate-search/standalone/) は、設定プロパティーを介して変更できます。

quarkus.hibernate-search-standalone.management.root-path=custom-root-path (1)
1 Hibernate Search の管理エンドポイントにカスタムの custom-root-path パスを使用します。 デフォルトの管理ルートパスが使用される場合は、インデックスが再作成されたパスは /q/custom-root-path/reindex になります。

このエンドポイントは、application/json コンテンツタイプのみの POST リクエストを受け入れます。 空のリクエスト本文が送信された場合、インデックスが作成されたすべてのエンティティーはインデックスが再作成されます。

エンティティータイプのインデックスを再作成するには、 configured for loading from an external source である必要があります。

この設定がない場合、管理エンドポイント (または他の API) を介してインデックスの再作成を行うと、 失敗します。

エンティティーのサブセットのみのインデックスを再作成する必要がある場合、または 基礎となる一括インデクサーのカスタム設定が必要な場合は、 以下に示すように、この情報をリクエスト本体を通じて渡すことができます。

{
  "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 インデックスの作成後に各インデックスが 1 つのセグメントにマージされるかどうか。
10 インデックスの作成直前に、最初のインデックスのパージ後に各インデックスが 1 つのセグメントにマージされるかどうか。
11 インデックスの作成前に、インデックスとそのスキーマ (存在する場合) を削除して再作成するかどうか。
12 インデックスの作成前に、すべてのエンティティーがインデックスから削除されるかどうか。
13 プライマリーキーをロードする際に使用するフェッチサイズの指定 (インデックスを作成するオブジェクトの場合)。
14 インデックスを再作成する ID とエンティティーをロードするためのトランザクションのタイムアウトの指定。

JSON 内のすべてのプロパティーはオプションであり、使用できるのは必要なものだけである点に注意してください。

一括インデクサーの設定に関する詳細は、 Hibernate Search リファレンスドキュメントの対応するセクション を参照してください。

インデックスの再作成要求を送信すると、バックグラウンドでインデックスの作成がトリガーされます。インデックスの一括作成の進行状況はアプリケーションログに表示されます。 テスト目的の場合、インデックスの作成がいつ終了したかを知ることは役に立つかもしれません。URL に wait_for=finished クエリーパラメーターを追加すると、 管理エンドポイントが、インデックス作成の開始時と終了時を報告するチャンク化された応答を返します。

制限

  • Hibernate Search Standalone エクステンションは、 Hibernate ORM を使用した Hibernate Search エクステンション と同じアプリケーションでは使用できません。

    進捗状況を追跡するには、https://github.com/quarkusio/quarkus/issues/39517[#39517] を参照してください。

  • Hibernate ORM を使用した Hibernate Search エクステンション とは異なり、 AWS リクエスト署名は現在利用できません。

    進捗状況を追跡するには、https://github.com/quarkusio/quarkus/issues/26991[#26991] を参照してください。

  • 楽観的並行性制御は現在利用できません。

    進捗状況を追跡するには、https://hibernate.atlassian.net/browse/HSEARCH-5105[HSEARCH-5105] を参照してください。

  • Elasticsearch/OpenSearch はトランザクションをサポートしていません。 そのため、複数のドキュメントの更新が部分的に失敗し、インデックスが不整合な状態になる可能性があります。

    これは、送信トレイポーリングによる調整 により、 Hibernate ORM を使用した Hibernate Search エクステンション のように回避することはできません。 なぜなら、その調整には Hibernate ORM が必要であり、 そのデータが (トランザクション) リレーショナルデータベースのデータから取得されるという事実に依存しているからです。

さらに詳しく

Hibernate Search の詳細については、 Hibernate チームが公開している 多数の参照ドキュメント および その他の関連ドキュメント を参照してください。

FAQ

なぜ Elasticsearch だけなのですか?

Hibernate Search は Lucene バックエンドと Elasticsearch バックエンドの両方をサポートしています。

Quarkus のコンテキストおよびスケーラブルなアプリケーションの構築において、Elasticsearch バックエンドの方適しています。 そこで、Elasticsearch バックエンドに重点を置いています。

現時点では Quarkus で Lucene バックエンドをサポートする予定はありません。 ただし、Quarkiverse (quarkiverse/quarkus-hibernate-search-extras#180) では、 このような実装の進捗状況が追跡されています。

Hibernate Search Standalone の設定リファレンス

ビルド時に固定された設定プロパティー。その他の設定プロパティーはすべてランタイム時にオーバーライド可能です。

Configuration property

タイプ

デフォルト

Whether Hibernate Search Standalone is enabled during the build.

If Hibernate Search is disabled during the build, all processing related to Hibernate Search will be skipped, but it will not be possible to activate Hibernate Search at runtime: quarkus.hibernate-search-standalone.active will default to false and setting it to true will lead to an error.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_ENABLED

Show more

boolean

true

A bean reference to a component that should be notified of any failure occurring in a background process (mainly index operations).

The referenced bean must implement FailureHandler.

Instead of setting this configuration property, you can simply annotate your custom FailureHandler implementation with @SearchExtension and leave the configuration property unset: Hibernate Search will use the annotated implementation automatically. See this section for more information.

If this configuration property is set, it takes precedence over any @SearchExtension annotation.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_BACKGROUND_FAILURE_HANDLER

Show more

string

One or more bean references to the component(s) used to configure the Hibernate Search mapping, in particular programmatically.

The referenced beans must implement StandalonePojoMappingConfigurer.

See Programmatic mapping for an example on how mapping configurers can be used to apply programmatic mappings.

Instead of setting this configuration property, you can simply annotate your custom StandalonePojoMappingConfigurer implementations with @SearchExtension and leave the configuration property unset: Hibernate Search will use the annotated implementation automatically. See this section for more information.

If this configuration property is set, it takes precedence over any @SearchExtension annotation.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_MAPPING_CONFIGURER

Show more

list of string

The structure of the Hibernate Search entity mapping.

This must match the structure of the application model being indexed with Hibernate Search:

graph (default)

Entities indexed through Hibernate Search are nodes in an entity graph, i.e. an indexed entity is independent of other entities it references through associations, which can be updated independently of the indexed entity.

Associations between entities must be bi-directional: specifying the inverse side of associations through @AssociationInverseSide is required, unless reindexing is disabled for that association through @IndexingDependency(reindexOnUpdate = …​).

document

Entities indexed through Hibernate Search are the root of a document, i.e. an indexed entity "owns" other entities it references through associations, which cannot be updated independently of the indexed entity.

Associations between entities can be uni-directional: specifying the inverse side of associations through @AssociationInverseSide is not required.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_MAPPING_STRUCTURE

Show more

graphEntities indexed through Hibernate Search are nodes in an entity graph. With this structure\: * An indexed entity is independent of other entities it references through associations, which can be updated independently of the indexed entity; in particular they may be passed to {@link org.hibernate.search.mapper.pojo.standalone.work.SearchIndexingPlan#addOrUpdate(Object)}. * Therefore, when an entity changes, Hibernate Search may need to resolve other entities to reindex, which means in particular that associations between entities must be bi-directional\: specifying the inverse side of associations through @AssociationInverseSide is required, unless reindexing is disabled for that association through @IndexingDependency(reindexOnUpdate = …​). See also link\:https://docs.jboss.org/hibernate/search/7.2/reference/en-US/html_single/#mapping-reindexing-associationinverseside\]@AssociationInverseSide] link\:https://docs.jboss.org/hibernate/search/7.2/reference/en-US/html_single/#mapping-reindexing-reindexonupdate\]@IndexingDependency(reindexOnUpdate = …​)]., documentEntities indexed through Hibernate Search are the root of a document. With this structure\: * An indexed entity "owns" other entities it references through associations, which cannot be updated independently of the indexed entity; in particular they cannot be passed to {@link org.hibernate.search.mapper.pojo.standalone.work.SearchIndexingPlan#addOrUpdate(Object)}. * Therefore, when an entity changes, Hibernate Search doesn’t need to resolve other entities to reindex, which means in particular that associations between entities can be uni-directional\: specifying the inverse side of associations through @AssociationInverseSide is not required. See also link\:https://docs.jboss.org/hibernate/search/7.2/reference/en-US/html_single/#mapping-reindexing-associationinverseside\]@AssociationInverseSide].

graphEntities indexed through Hibernate Search are nodes in an entity graph. With this structure\: * An indexed entity is independent of other entities it references through associations, which can be updated independently of the indexed entity; in particular they may be passed to {@link org.hibernate.search.mapper.pojo.standalone.work.SearchIndexingPlan#addOrUpdate(Object)}. * Therefore, when an entity changes, Hibernate Search may need to resolve other entities to reindex, which means in particular that associations between entities must be bi-directional\: specifying the inverse side of associations through @AssociationInverseSide is required, unless reindexing is disabled for that association through @IndexingDependency(reindexOnUpdate = …​). See also link\:https://docs.jboss.org/hibernate/search/7.2/reference/en-US/html_single/#mapping-reindexing-associationinverseside\]@AssociationInverseSide] link\:https://docs.jboss.org/hibernate/search/7.2/reference/en-US/html_single/#mapping-reindexing-reindexonupdate\]@IndexingDependency(reindexOnUpdate = …​)].

Whether Hibernate Search Standalone should be active at runtime.

If Hibernate Search Standalone is not active, it won’t start with the application, and accessing the SearchMapping for search or other operations will not be possible.

Note that if Hibernate Search Standalone is disabled (i.e. quarkus.hibernate-search-standalone.enabled is set to false), it won’t be active, and setting this property to true will fail.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_ACTIVE

Show more

boolean

'true' if Hibernate Search Standalone is enabled; 'false' otherwise

The schema management strategy, controlling how indexes and their schema are created, updated, validated or dropped on startup and shutdown.

Available values:

Strategy

Definition

none

Do nothing: assume that indexes already exist and that their schema matches Hibernate Search’s expectations.

validate

Validate that indexes exist and that their schema matches Hibernate Search’s expectations.

If it does not, throw an exception, but make no attempt to fix the problem.

create

For indexes that do not exist, create them along with their schema.

For indexes that already exist, do nothing: assume that their schema matches Hibernate Search’s expectations.

create-or-validate (default unless using Dev Services)

For indexes that do not exist, create them along with their schema.

For indexes that already exist, validate that their schema matches Hibernate Search’s expectations.

If it does not, throw an exception, but make no attempt to fix the problem.

create-or-update

For indexes that do not exist, create them along with their schema.

For indexes that already exist, validate that their schema matches Hibernate Search’s expectations; if it does not match expectations, try to update it.

This strategy is unfit for production environments, due to several important limitations, but can be useful when developing.

drop-and-create

For indexes that do not exist, create them along with their schema.

For indexes that already exist, drop them, then create them along with their schema.

drop-and-create-and-drop (default when using Dev Services)

For indexes that do not exist, create them along with their schema.

For indexes that already exist, drop them, then create them along with their schema.

Also, drop indexes and their schema on shutdown.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_SCHEMA_MANAGEMENT_STRATEGY

Show more

none, validate, create, create-or-validate, create-or-update, drop-and-create, drop-and-create-and-drop

drop-and-create-and-drop when using Dev Services; create-or-validate otherwise

How to synchronize between application threads and indexing, in particular when relying on (implicit) listener-triggered indexing on entity change, but also when using a SearchIndexingPlan explicitly.

Defines how complete indexing should be before resuming the application thread after a SearchSession is closed.

Available values:

Strategy

Throughput

Guarantees when the application thread resumes

Changes applied

Changes safe from crash/power loss

Changes visible on search

async

Best

write-sync (default)

Medium

read-sync

Medium to worst

sync

Worst

This property also accepts a bean reference to a custom implementations of IndexingPlanSynchronizationStrategy.

Instead of setting this configuration property, you can simply annotate your custom IndexingPlanSynchronizationStrategy implementation with @SearchExtension and leave the configuration property unset: Hibernate Search will use the annotated implementation automatically. If this configuration property is set, it takes precedence over any @SearchExtension annotation.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_INDEXING_PLAN_SYNCHRONIZATION_STRATEGY

Show more

string

write-sync

Configuration for backends

タイプ

デフォルト

quarkus.hibernate-search-standalone.elasticsearch."backend-name".version

The version of Elasticsearch used in the cluster.

As the schema is generated without a connection to the server, this item is mandatory.

It doesn’t have to be the exact version (it can be 7 or 7.1 for instance) but it has to be sufficiently precise to choose a model dialect (the one used to generate the schema) compatible with the protocol dialect (the one used to communicate with Elasticsearch).

There’s no rule of thumb here as it depends on the schema incompatibilities introduced by Elasticsearch versions. In any case, if there is a problem, you will have an error when Hibernate Search tries to connect to the cluster.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_ELASTICSEARCH_VERSION

Show more

ElasticsearchVersion

quarkus.hibernate-search-standalone.elasticsearch."backend-name".schema-management.settings-file

Path to a file in the classpath holding custom index settings to be included in the index definition when creating an Elasticsearch index.

The provided settings will be merged with those generated by Hibernate Search, including analyzer definitions. When analysis is configured both through an analysis configurer and these custom settings, the behavior is undefined; it should not be relied upon.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_ELASTICSEARCH_SCHEMA_MANAGEMENT_SETTINGS_FILE

Show more

string

quarkus.hibernate-search-standalone.elasticsearch."backend-name".schema-management.mapping-file

Path to a file in the classpath holding a custom index mapping to be included in the index definition when creating an Elasticsearch index.

The file does not need to (and generally shouldn’t) contain the full mapping: Hibernate Search will automatically inject missing properties (index fields) in the given mapping.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_ELASTICSEARCH_SCHEMA_MANAGEMENT_MAPPING_FILE

Show more

string

quarkus.hibernate-search-standalone.elasticsearch."backend-name".analysis.configurer

One or more bean references to the component(s) used to configure full text analysis (e.g. analyzers, normalizers).

The referenced beans must implement ElasticsearchAnalysisConfigurer.

See Setting up the analyzers for more information.

Instead of setting this configuration property, you can simply annotate your custom ElasticsearchAnalysisConfigurer implementations with @SearchExtension and leave the configuration property unset: Hibernate Search will use the annotated implementation automatically. See this section for more information.

If this configuration property is set, it takes precedence over any @SearchExtension annotation.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_ELASTICSEARCH_ANALYSIS_CONFIGURER

Show more

list of string

quarkus.hibernate-search-standalone.elasticsearch."backend-name".hosts

The list of hosts of the Elasticsearch servers.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_ELASTICSEARCH_HOSTS

Show more

list of string

localhost:9200

quarkus.hibernate-search-standalone.elasticsearch."backend-name".protocol

The protocol to use when contacting Elasticsearch servers. Set to "https" to enable SSL/TLS.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_ELASTICSEARCH_PROTOCOL

Show more

httpUse clear-text HTTP, with SSL/TLS disabled., httpsUse HTTPS, with SSL/TLS enabled.

httpUse clear-text HTTP, with SSL/TLS disabled.

quarkus.hibernate-search-standalone.elasticsearch."backend-name".username

The username used for authentication.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_ELASTICSEARCH_USERNAME

Show more

string

quarkus.hibernate-search-standalone.elasticsearch."backend-name".password

The password used for authentication.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_ELASTICSEARCH_PASSWORD

Show more

string

quarkus.hibernate-search-standalone.elasticsearch."backend-name".connection-timeout

The timeout when establishing a connection to an Elasticsearch server.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_ELASTICSEARCH_CONNECTION_TIMEOUT

Show more

Duration 

1S

quarkus.hibernate-search-standalone.elasticsearch."backend-name".read-timeout

The timeout when reading responses from an Elasticsearch server.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_ELASTICSEARCH_READ_TIMEOUT

Show more

Duration 

30S

quarkus.hibernate-search-standalone.elasticsearch."backend-name".request-timeout

The timeout when executing a request to an Elasticsearch server.

This includes the time needed to wait for a connection to be available, send the request and read the response.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_ELASTICSEARCH_REQUEST_TIMEOUT

Show more

Duration 

quarkus.hibernate-search-standalone.elasticsearch."backend-name".max-connections

The maximum number of connections to all the Elasticsearch servers.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_ELASTICSEARCH_MAX_CONNECTIONS

Show more

int

20

quarkus.hibernate-search-standalone.elasticsearch."backend-name".max-connections-per-route

The maximum number of connections per Elasticsearch server.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_ELASTICSEARCH_MAX_CONNECTIONS_PER_ROUTE

Show more

int

10

quarkus.hibernate-search-standalone.elasticsearch."backend-name".discovery.enabled

Defines if automatic discovery is enabled.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_ELASTICSEARCH_DISCOVERY_ENABLED

Show more

boolean

false

quarkus.hibernate-search-standalone.elasticsearch."backend-name".discovery.refresh-interval

Refresh interval of the node list.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_ELASTICSEARCH_DISCOVERY_REFRESH_INTERVAL

Show more

Duration 

10S

quarkus.hibernate-search-standalone.elasticsearch."backend-name".thread-pool.size

The size of the thread pool assigned to the backend.

Note that number is per backend, not per index. Adding more indexes will not add more threads.

As all operations happening in this thread-pool are non-blocking, raising its size above the number of processor cores available to the JVM will not bring noticeable performance benefit. The only reason to alter this setting would be to reduce the number of threads; for example, in an application with a single index with a single indexing queue, running on a machine with 64 processor cores, you might want to bring down the number of threads.

Defaults to the number of processor cores available to the JVM on startup.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_ELASTICSEARCH_THREAD_POOL_SIZE

Show more

int

quarkus.hibernate-search-standalone.elasticsearch."backend-name".query.shard-failure.ignore

Whether partial shard failures are ignored (true) or lead to Hibernate Search throwing an exception (false).

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_ELASTICSEARCH_QUERY_SHARD_FAILURE_IGNORE

Show more

boolean

false

quarkus.hibernate-search-standalone.elasticsearch."backend-name".version-check.enabled

Whether Hibernate Search should check the version of the Elasticsearch cluster on startup.

Set to false if the Elasticsearch cluster may not be available on startup.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_ELASTICSEARCH_VERSION_CHECK_ENABLED

Show more

boolean

true

quarkus.hibernate-search-standalone.elasticsearch."backend-name".schema-management.required-status

The minimal Elasticsearch cluster status required on startup.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_ELASTICSEARCH_SCHEMA_MANAGEMENT_REQUIRED_STATUS

Show more

green, yellow, red

yellow

quarkus.hibernate-search-standalone.elasticsearch."backend-name".schema-management.required-status-wait-timeout

How long we should wait for the status before failing the bootstrap.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_ELASTICSEARCH_SCHEMA_MANAGEMENT_REQUIRED_STATUS_WAIT_TIMEOUT

Show more

Duration 

10S

quarkus.hibernate-search-standalone.elasticsearch."backend-name".indexing.queue-count

The number of indexing queues assigned to each index.

Higher values will lead to more connections being used in parallel, which may lead to higher indexing throughput, but incurs a risk of overloading Elasticsearch, i.e. of overflowing its HTTP request buffers and tripping circuit breakers, leading to Elasticsearch giving up on some request and resulting in indexing failures.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_ELASTICSEARCH_INDEXING_QUEUE_COUNT

Show more

int

10

quarkus.hibernate-search-standalone.elasticsearch."backend-name".indexing.queue-size

The size of indexing queues.

Lower values may lead to lower memory usage, especially if there are many queues, but values that are too low will reduce the likeliness of reaching the max bulk size and increase the likeliness of application threads blocking because the queue is full, which may lead to lower indexing throughput.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_ELASTICSEARCH_INDEXING_QUEUE_SIZE

Show more

int

1000

quarkus.hibernate-search-standalone.elasticsearch."backend-name".indexing.max-bulk-size

The maximum size of bulk requests created when processing indexing queues.

Higher values will lead to more documents being sent in each HTTP request sent to Elasticsearch, which may lead to higher indexing throughput, but incurs a risk of overloading Elasticsearch, i.e. of overflowing its HTTP request buffers and tripping circuit breakers, leading to Elasticsearch giving up on some request and resulting in indexing failures.

Note that raising this number above the queue size has no effect, as bulks cannot include more requests than are contained in the queue.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_ELASTICSEARCH_INDEXING_MAX_BULK_SIZE

Show more

int

100

quarkus.hibernate-search-standalone.elasticsearch."backend-name".layout.strategy

A bean reference to the component used to configure the Elasticsearch layout: index names, index aliases, …​

The referenced bean must implement IndexLayoutStrategy.

Available built-in implementations:

simple

The default, future-proof strategy: if the index name in Hibernate Search is myIndex, this strategy will create an index named myindex-000001, an alias for write operations named myindex-write, and an alias for read operations named myindex-read.

no-alias

A strategy without index aliases, mostly useful on legacy clusters: if the index name in Hibernate Search is myIndex, this strategy will create an index named myindex, and will not use any alias.

Instead of setting this configuration property, you can simply annotate your custom IndexLayoutStrategy implementation with @SearchExtension and leave the configuration property unset: Hibernate Search will use the annotated implementation automatically. See this section for more information.

If this configuration property is set, it takes precedence over any @SearchExtension annotation.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_ELASTICSEARCH_LAYOUT_STRATEGY

Show more

string

Per-index configuration overrides

タイプ

デフォルト

quarkus.hibernate-search-standalone.elasticsearch."backend-name".indexes."index-name".schema-management.settings-file

Path to a file in the classpath holding custom index settings to be included in the index definition when creating an Elasticsearch index.

The provided settings will be merged with those generated by Hibernate Search, including analyzer definitions. When analysis is configured both through an analysis configurer and these custom settings, the behavior is undefined; it should not be relied upon.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_ELASTICSEARCH_INDEXES__INDEX_NAME__SCHEMA_MANAGEMENT_SETTINGS_FILE

Show more

string

quarkus.hibernate-search-standalone.elasticsearch."backend-name".indexes."index-name".schema-management.mapping-file

Path to a file in the classpath holding a custom index mapping to be included in the index definition when creating an Elasticsearch index.

The file does not need to (and generally shouldn’t) contain the full mapping: Hibernate Search will automatically inject missing properties (index fields) in the given mapping.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_ELASTICSEARCH_INDEXES__INDEX_NAME__SCHEMA_MANAGEMENT_MAPPING_FILE

Show more

string

quarkus.hibernate-search-standalone.elasticsearch."backend-name".indexes."index-name".analysis.configurer

One or more bean references to the component(s) used to configure full text analysis (e.g. analyzers, normalizers).

The referenced beans must implement ElasticsearchAnalysisConfigurer.

See Setting up the analyzers for more information.

Instead of setting this configuration property, you can simply annotate your custom ElasticsearchAnalysisConfigurer implementations with @SearchExtension and leave the configuration property unset: Hibernate Search will use the annotated implementation automatically. See this section for more information.

If this configuration property is set, it takes precedence over any @SearchExtension annotation.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_ELASTICSEARCH_INDEXES__INDEX_NAME__ANALYSIS_CONFIGURER

Show more

list of string

quarkus.hibernate-search-standalone.elasticsearch."backend-name".indexes."index-name".schema-management.required-status

The minimal Elasticsearch cluster status required on startup.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_ELASTICSEARCH_INDEXES__INDEX_NAME__SCHEMA_MANAGEMENT_REQUIRED_STATUS

Show more

green, yellow, red

yellow

quarkus.hibernate-search-standalone.elasticsearch."backend-name".indexes."index-name".schema-management.required-status-wait-timeout

How long we should wait for the status before failing the bootstrap.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_ELASTICSEARCH_INDEXES__INDEX_NAME__SCHEMA_MANAGEMENT_REQUIRED_STATUS_WAIT_TIMEOUT

Show more

Duration 

10S

quarkus.hibernate-search-standalone.elasticsearch."backend-name".indexes."index-name".indexing.queue-count

The number of indexing queues assigned to each index.

Higher values will lead to more connections being used in parallel, which may lead to higher indexing throughput, but incurs a risk of overloading Elasticsearch, i.e. of overflowing its HTTP request buffers and tripping circuit breakers, leading to Elasticsearch giving up on some request and resulting in indexing failures.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_ELASTICSEARCH_INDEXES__INDEX_NAME__INDEXING_QUEUE_COUNT

Show more

int

10

quarkus.hibernate-search-standalone.elasticsearch."backend-name".indexes."index-name".indexing.queue-size

The size of indexing queues.

Lower values may lead to lower memory usage, especially if there are many queues, but values that are too low will reduce the likeliness of reaching the max bulk size and increase the likeliness of application threads blocking because the queue is full, which may lead to lower indexing throughput.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_ELASTICSEARCH_INDEXES__INDEX_NAME__INDEXING_QUEUE_SIZE

Show more

int

1000

quarkus.hibernate-search-standalone.elasticsearch."backend-name".indexes."index-name".indexing.max-bulk-size

The maximum size of bulk requests created when processing indexing queues.

Higher values will lead to more documents being sent in each HTTP request sent to Elasticsearch, which may lead to higher indexing throughput, but incurs a risk of overloading Elasticsearch, i.e. of overflowing its HTTP request buffers and tripping circuit breakers, leading to Elasticsearch giving up on some request and resulting in indexing failures.

Note that raising this number above the queue size has no effect, as bulks cannot include more requests than are contained in the queue.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_ELASTICSEARCH_INDEXES__INDEX_NAME__INDEXING_MAX_BULK_SIZE

Show more

int

100

Management interface

タイプ

デフォルト

Root path for reindexing endpoints. This value will be resolved as a path relative to ${quarkus.management.root-path}.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_MANAGEMENT_ROOT_PATH

Show more

string

hibernate-search/standalone/

If management interface is turned on the reindexing endpoints will be published under the management interface. This property allows to enable this functionality by setting it to `true.

Environment variable: QUARKUS_HIBERNATE_SEARCH_STANDALONE_MANAGEMENT_ENABLED

Show more

boolean

false

期間フォーマットについて

To write duration values, use the standard java.time.Duration format. See the Duration#parse() Java API documentation for more information.

数字で始まる簡略化した書式を使うこともできます:

  • 数値のみの場合は、秒単位の時間を表します。

  • 数値の後に ms が続く場合は、ミリ秒単位の時間を表します。

その他の場合は、簡略化されたフォーマットが解析のために java.time.Duration フォーマットに変換されます:

  • 数値の後に hms が続く場合は、その前に PT が付けられます。

  • 数値の後に d が続く場合は、その前に P が付けられます。

Bean 参照について

まず、設定プロパティーで Bean を参照することはオプションであり、実際には推奨されていないことに注意してください。 Bean に @SearchExtension アノテーションを付けることによって、同じ結果を得ることができます。 詳細は this section を参照してください。

設定プロパティーで文字列値を使用して Bean を参照したい場合は、 文字列が解析されることを確認します。最も一般的な形式は次のとおりです。

  • bean: の後に @Named CDI Bean の名前が続きます。 たとえば bean:myBean のようになります。

  • class: の後にクラスの完全修飾名を付けて、CDI Bean の場合は CDI を通して、 そうでない場合はパブリックで引数なしのコンストラクターを通してインスタンス化されます。 たとえば class:com.mycompany.MyClass のようになります。

  • 組み込み実装を参照する任意の文字列。 利用可能な値については、各設定プロパティーのドキュメントに詳細が記載されています (quarkus.hibernate-search-standalone.indexing.plan.synchronization.strategyasync/read-sync/write-sync/sync など)。

他の形式も認められていますが、高度なユースケースでのみ有用です。 詳細は、Hibernate Searchの参照ドキュメントのこちらのセクション を参照してください。

関連コンテンツ