第5章 クエリ


Hibernate Search の 2 番目に重要な機能は、Lucene クエリを実行し、Hibernate セッションにより管理されたエンティティを取得する機能です (これにより、Hibernate のパラダイム内で Lucene の能力が提供され、Hibernate の従来の検索メカニズム (HQL、基準クエリ、ネイティブ SQL クエリ) に別の次元が提供されます。クエリの準備と実行は 4 つの単純な手順から構成されます。
  • FullTextSession の作成
  • Lucene クエリの作成
  • org.hibernate.Query を使用した Lucene クエリのラップ
  • list()scroll() などを呼び出して検索を実行
クエリ機能にアクセスするには、FullTextSession を使用する必要があります。この検索固有のセッションは、通常の org.hibernate.Session をラップしてクエリ機能とインデックス機能を提供します。

例5.1 FullTextSession の作成

Session session = sessionFactory.openSession();
...
FullTextSession fullTextSession = Search.getFullTextSession(session);
Copy to Clipboard Toggle word wrap
実際の検索機能は、以下の例で示されたネイティブの Lucene クエリに基づいて構築されます。

例5.2 Lucene クエリの作成

org.apache.lucene.queryParser.QueryParser parser = 
    new QueryParser("title", new StopAnalyzer() );

org.apache.lucene.search.Query luceneQuery = parser.parse( "summary:Festina Or brand:Seiko" );
org.hibernate.Query fullTextQuery = fullTextSession.createFullTextQuery( luceneQuery ); 
List result = fullTextQuery.list(); //return a list of managed objects
Copy to Clipboard Toggle word wrap
Lucene クエリ上に構築された Hibernate クエリは通常の org.hibernate.Query です。つまり、他の Hibernate クエリ機能 (HQL、Native、または Criteria) と同じパラダイムに属しています。通常の list()uniqueResult()iterate()、および scroll() メソッドを使用できます。
Hibernate の Java Persistence API (EJB 3.0 Persistence とも呼ばれます) を使用している場合は、同じ拡張機能が存在します。

例5.3 JPA API を使用した検索クエリの作成

EntityManager em = entityManagerFactory.createEntityManager();

FullTextEntityManager fullTextEntityManager = 
    org.hibernate.hibernate.search.jpa.Search.getFullTextEntityManager(em);

...
org.apache.lucene.queryParser.QueryParser parser = 
    new QueryParser("title", new StopAnalyzer() );

org.apache.lucene.search.Query luceneQuery = parser.parse( "summary:Festina Or brand:Seiko" );
javax.persistence.Query fullTextQuery = fullTextEntityManager.createFullTextQuery( luceneQuery );

List result = fullTextQuery.getResultList(); //return a list of managed objects
Copy to Clipboard Toggle word wrap
以下の例では、Hibernate API を使用します。ただし、同じ例は、Java Persistence API を使用して FullTextQuery が取得される方法を調整することによって簡単に書き換えることができます。

5.1. クエリの構築

Hibernate Search クエリは Lucene クエリの上部に構築され、実行する Lucene クエリのタイプはまったく関係ありません。ただし、構築された Hibernate Search は org.hibernate.Query を主なクエリ操作 API として使用してクエリ処理をラップします。

5.1.1. Lucene クエリの構築

Lucene クエリの実際の構築方法については、このドキュメンテーションの範囲外です。オンラインの Lucene ドキュメンテーションまたは『Lucene In Action』あるいは『Hibernate Search in Action』を参照してください。

5.1.2. Hibernate Search クエリの構築

5.1.2.1. 概要

Lucene クエリが構築されたら、Lucene クエリを Hibernate Query にラップする必要があります。

例5.4 Hibernate Query への Lucene クエリのラップ

FullTextSession fullTextSession = Search.getFullTextSession( session );
org.hibernate.Query fullTextQuery = fullTextSession.createFullTextQuery( luceneQuery );
Copy to Clipboard Toggle word wrap
特に指定がない限りクエリはインデックス化されたすべてのエンティティに対して実行されます (場合によっては、インデックス化されたクラスのすべてのタイプが返されます)。パフォーマンスの観点から、返されるタイプを制限することが推奨されます。

例5.5 エンティティタイプによる検索結果のフィルタリング

org.hibernate.Query fullTextQuery = fullTextSession.createFullTextQuery( luceneQuery, Customer.class );
// or
fullTextQuery = fullTextSession.createFullTextQuery( luceneQuery, Item.class, Actor.class );
Copy to Clipboard Toggle word wrap
最初の例は一致する Customer だけを返し、2 つ目の例は一致する ActorItem を返します。タイプの制限は完全にポリモーフィックです。つまり、基本クラス Person の、2 つのインデックス化されたサブクラスSalesmanCustomer が存在する場合、結果タイプに基づいてフィルタするには Person.class を指定します。

5.1.2.2. ページ処理

パフォーマンス上の理由から、1 つのクエリに対して返されるオブジェクトの数を制限することが推奨されます。ユーザーがあるページから別のページに移動することは実際にはよくあることです。ページ処理を定義する方法は、プレーンな HQL または基準クエリでページ処理を定義する方法とまったく同じです。

例5.6 検索クエリのページ処理の定義

org.hibernate.Query fullTextQuery = fullTextSession.createFullTextQuery( luceneQuery, Customer.class );
fullTextQuery.setFirstResult(15); //start from the 15th element
fullTextQuery.setMaxResults(10); //return 10 elements
Copy to Clipboard Toggle word wrap

注記

fulltextQuery.getResultSize() を使用すると、ページ処理に関係なく一致するエレメントの合計数を取得できます。

5.1.2.3. ソート

Apache Lucene を使用すると、結果を非常に柔軟かつ強力にソートできます。ほとんどの場合はデフォルトのソート (重要度別) が適切ですが、1 つまたは複数の他のプロパティによってソートすることもできます。これを行うには、Lucene Sort オブジェクトが Lucene ソート方針を適用するよう設定します。

例5.7 結果をソートするための Lucene Sort の指定

org.hibernate.search.FullTextQuery query = s.createFullTextQuery( query, Book.class );
org.apache.lucene.search.Sort sort = new Sort(new SortField("title"));
query.setSort(sort);
List results = query.list();
Copy to Clipboard Toggle word wrap
FullTextQuery インタフェースが org.hibernate.Query のサブインタフェースであることに気づかれるかもしれません。ソートに使用されるフィールドはトークン化しないよう注意してください。

5.1.2.4. フェッチ方針

戻り値のタイプを 1 つのクラスに制限する場合、Hibernate Search は単一のクエリを使用してオブジェクトをロードします。また、ドメインモデルで定義された静的なフェッチ方針が優先されます。
ただし、多くの場合、特定の使用例のためにフェッチ方針を調整することが役に立ちます。

例5.8 クエリでの FetchMode の指定

Criteria criteria = s.createCriteria( Book.class ).setFetchMode( "authors", FetchMode.JOIN );
s.createFullTextQuery( luceneQuery ).setCriteriaQuery( criteria );
Copy to Clipboard Toggle word wrap
この例では、クエリは luceneQuery に一致するすべての本を返します。作者コレクションは SQL 外部結合を使用して同じクエリからロードされます。
基準クエリを定義する場合は、完全テキストセッションから Hibernate Search クエリを作成するときに返されるエンティティタイプを制限する必要はありません。タイプは基準クエリ自体から推測されます。フェッチモードのみを調整し、他の制限の適用を回避できます。
複数のエンティティが返されることが期待される場合は、setCriteriaQuery を使用できません。

5.1.2.5. プロジェクション

場合によっては、ドメインオブジェクト (グラフ) を返すことがやりすぎになることがあります。Hibernate Search では、プロパティのサブセットを返すことができます。

例5.9 完全なドメインオブジェクトを返す代わりにプロジェクションを使用

org.hibernate.search.FullTextQuery query = s.createFullTextQuery( luceneQuery, Book.class );
query.setProjection( "id", "summary", "body", "mainAuthor.name" );
List results = query.list();
Object[] firstResult = (Object[]) results.get(0);
  Integer id = (Integer) firstResult[0];
  String summary = (String) firstResult[1];
  String body = (String) firstResult[2];
  String authorName = (String) firstResult[3];
Copy to Clipboard Toggle word wrap
Hibernate Search は Lucene インデックスからプロパティを抽出し、オブジェクト形式に再び変換します (Object[] のリストが返されます)。プロジェクションにより、潜在的なデータベースラウンドトリップ (クエリの応答時間が重要な場合に有用) が回避されますが、いくつかの制限が存在します。
  • 予測されたプロパティはインデックス (@Field(store=Store.YES)) に格納する必要があります (これによりインデックスサイズが増加します)。
  • 予測されたプロパティは、org.hibernate.search.bridge.TwoWayFieldBridge または org.hibernate.search.bridge.TwoWayStringBridge (単純なバージョン) を実装する FieldBridge を使用する必要があります。すべての Hibernate Search 組込みタイプは両方向です。
  • インデックス化されたエンティティまたは組み込まれた関係の単純なプロパティのみを予測できます。つまり、組み込まれたエンティティ全体を予測できません。
  • プロジェクションは、@IndeedEmbedded を使用してインデックス化されたコレクションまたはマップに対して機能しません。
プロジェクションは、別の場合にも役に立ちます。Lucene は結果に関するいくつかのメタデータ情報をユーザーに提供します。いくつかの特殊なプレースホルダーを使用することにより、プロジェクションメカニズムはこれらのメタデータを取得できます。

例5.10 メタデータを取得するためにプロジェクションを使用

org.hibernate.search.FullTextQuery query = s.createFullTextQuery( luceneQuery, Book.class );
query.setProjection( FullTextQuery.SCORE, FullTextQuery.THIS, "mainAuthor.name" );
List results = query.list();
Object[] firstResult = (Object[]) results.get(0);
  float score = (Float) firstResult[0];
  Book book = (Book) firstResult[1];
  String authorName = (String) firstResult[2];
Copy to Clipboard Toggle word wrap
通常のフィールドと特殊なプレースホルダーは混在させることができます。利用可能なプレースホルダーのリストは以下のとおりです。
  • FullTextQuery.THIS: 初期化および管理されたエンティティを返します (予測されないクエリの場合と同様)。
  • FullTextQuery.DOCUMENT: 予測されたオブジェクトに関連する Lucene Document を返します。
  • FullTextQuery.OBJECT_CLASS: インデックス化されたエンティティのクラスを返します。
  • FullTextQuery.SCORE: クエリのドキュメンテーションスコアを返します。スコアはある結果とクエリの他の結果を比較するのに役に立ちしますが、異なるクエリの結果を比較する場合は役に立ちません。
  • FullTextQuery.ID: 予測されたオブジェクトの id プロパティ値。
  • FullTextQuery.DOCUMENT_ID: Lucene ドキュメント id。Lucene ドキュメント id は 2 つの異なる IndexReader のオープン間で変わることがあることに注意してください (この機能は実験段階にあります)。
  • FullTextQuery.EXPLANATION: 該当するクエリの一致するオブジェクト/ドキュメントに対する Lucene Explanation オブジェクトを返します。たくさんのデータを取得する場合は使用しないでください。通常、Explanation を返すコストは、一致するエレメントごとに Lucene クエリ全体を実行するコストと同じです。
トップに戻る
Red Hat logoGithubredditYoutubeTwitter

詳細情報

試用、購入および販売

コミュニティー

Red Hat ドキュメントについて

Red Hat をお使いのお客様が、信頼できるコンテンツが含まれている製品やサービスを活用することで、イノベーションを行い、目標を達成できるようにします。 最新の更新を見る.

多様性を受け入れるオープンソースの強化

Red Hat では、コード、ドキュメント、Web プロパティーにおける配慮に欠ける用語の置き換えに取り組んでいます。このような変更は、段階的に実施される予定です。詳細情報: Red Hat ブログ.

会社概要

Red Hat は、企業がコアとなるデータセンターからネットワークエッジに至るまで、各種プラットフォームや環境全体で作業を簡素化できるように、強化されたソリューションを提供しています。

Theme

© 2025 Red Hat