AI エージェント向け: ドキュメントインデックスは https://www.mongodb.com/ja-jp/docs/llms.txt で利用できます。すべてのページの markdown バージョンは、いずれかの URL パスに .md を追加することで利用できます。

クエリを指定する

このガイドでは、Hibernate ORM 用の MongoDB 拡張機能を使用してデータベースクエリを指定する方法を学習します。

クエリフィルターを作成することで、クエリが返すドキュメントのセットを絞り込むことができます。クエリフィルターは、MongoDB が読み取りまたは書き込み (write) 操作においてドキュメントを照合するために使用する検索する条件を指定する式です。MongoDBクエリフィルターを作成するには、 非表示クエリ言語(HQL) または Java 永続クエリ言語(JQL) ステートメントを使用します。

Tip

HQL および JQL の構文の詳細については、非表示の ORM ドキュメントの「非表示のクエリ言語へのガイド」を参照してください。

注意

クエリ サポート

Hibernate ORM 用のMongoDB拡張機能は、すべてのMongoDBおよびHibernateのクエリ機能をサポートしていません。詳細については、 機能の互換性 ページの「クエリ サポート」を参照してください。

このガイドの例では、Atlasサンプルデータセットの sample_mflix.moviesコレクションを表す Movie エンティティを使用します。Movie エンティティには次の定義があります。

import com.mongodb.hibernate.annotations.ObjectIdGenerator;import org.bson.types.ObjectId;import java.time.Instant;import java.util.List;import jakarta.persistence.Embedded; import jakarta.persistence.Entity;import jakarta.persistence.FetchType;import jakarta.persistence.Id;import jakarta.persistence.OneToMany;import jakarta.persistence.Table; @Entity@Table(name = "movies")public class Movie { @Id @ObjectIdGenerator private ObjectId id; private String title; private String plot; private int year; private List<String> cast; private List<String> directors; private Instant released; @Embedded private Awards awards; @OneToMany(mappedBy = "movie", fetch = FetchType.LAZY) private List<Comment> comments; public Movie(String title, String plot, int year, List<String> cast, List<String> directors, Instant released, Awards awards) { this.title = title; this.plot = plot; this.year = year; this.cast = cast; this.directors = directors; this.released = released; this.awards = awards; } public Movie() { } public ObjectId getId() { return id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getPlot() { return plot; } public void setPlot(String plot) { this.plot = plot; } public int getYear() { return year; } public void setYear(int year) { this.year = year; } public List<String> getCast() { return cast; } public void setCast(List<String> cast) { this.cast = cast; } public List<String> getDirectors() { return directors; } public void setDirectors(List<String> directors) { this.directors = directors; } public Awards getAwards() { return awards; } public void setAwards(Awards awards) { this.awards = awards; } public Instant getReleased() { return released; } public void setReleased(Instant released) { this.released = released; } public List<Comment> getComments() { return comments; } public void setComments(List<Comment> comments) { this.comments = comments; }}

Hibernetes ORM 用のMongoDB拡張機能を使用してこのMongoDBサンプルコレクションと交流するJavaアプリケーションを作成する方法については、Get Started チュートリアルを参照してください。

このページのコード例では、次の Awards @Struct 集計埋め込み可能オブジェクトも使用します。

@Embeddable@Struct(name = "Awards")public class Awards { private int wins; private int nominations; private String text; public Awards(int wins, int nominations, String text) { this.wins = wins; this.nominations = nominations; this.text = text; } public Awards() { } public int getWins() { return wins; } public void setWins(int wins) { this.wins = wins; } public int getNominations() { return nominations; } public void setNominations(int nominations) { this.nominations = nominations; } public String getText() { return text; } public void setText(String text) { this.text = text; }}

重要

永続性コンテキスト

Hibernetes ORM を有効にしてデータベースを操作するには、 Hibernetes Session または Java 永続性 EntityManager を使用して永続性コンテキスト内で操作を実行する必要があります。セッション クエリを定義するには HQL を使用し、エンティティ マネージャー クエリを定義するには JQL を使用します。

このガイドの例を実行する前に、次のコードのような永続性コンテキストとトランザクションマネジメントコードをアプリケーションに追加していることを確認してください。

var sf = HibernateUtil.getSessionFactory();Session session = sf.openSession();Transaction tx = session.beginTransaction(); // ... Perform CRUD operations here tx.commit();session.close();sf.close();

セッションを使用するには、SessionFactory を構成する HibernateUtil.javaファイルを作成する必要があります。詳しく学ぶには、「使い始める」チュートリアルの「アプリケーションを構成する」手順を参照してください。

SessionFactory インスタンスを作成する前に、com.mongodb.hibernate.semantics.nulls 設定プロパティを MQL に設定する必要があります。このプロパティは必須であり、デフォルト値はなく、現在他の値は受け入れられません。プロパティを省略するか、別の値に設定すると、Hibernate ORM 拡張機能は HibernateException をスローします。

com.mongodb.hibernate.semantics.nulls を MQL に設定すると、このプロパティは、null 関連の動作が SQL の null セマンティクスで定義された 3 値論理ではなく、Hibernate ORM 拡張機能が変換中に生成する MongoDB クエリ言語 (MQL) に従うことを宣言します。

Hibernate ORM拡張機能は特定の変換を保証するものではないため、nullに関連する動作の結果はリリース間で変更される可能性があります。

次の例では、hibernate.properties ファイルの com.mongodb.hibernate.semantics.nulls プロパティを設定します。

com.mongodb.hibernate.semantics.nulls=MQL

クエリ ステートメントで次の演算子を使用して、フィールド値を指定されたクエリ値と比較できます。

  • =: 等価一致

  • <>: 等価一致

  • >: 比較より大きい

  • >=: 以上の比較

  • <: 比較より小さい

  • <=: 以下の比較

次の例では、sample_mflix.moviesコレクションから、year の値が 2015 以上であるドキュメントを検索します。

var comparisonResult = session.createQuery("from Movie where year >= :y", Movie.class) .setParameter("y", 2015) .getResultList();for (var m : comparisonResult) { System.out.println("Title: " + m.getTitle());}

行値述語は、括弧で囲まれたフィールドのリストを、括弧で囲まれた値のリストと単一の式で比較します。Hibernate ORM 拡張機能は、次の演算子を使用する行値述語をサポートしています。

  • =: 等価一致

  • <>: 等価一致

  • IN および NOT IN: 値の行のリストとの照合

値はバインドパラメータまたはリテラルとして指定できます。各リストには同じ数のコンポーネントが含まれている必要があります。

次の例では、sample_mflix.movies コレクションから、title 値が "Jurassic World" で、year 値が 2015 であるドキュメントを取得します。

var rowValueResult = session.createQuery("from Movie where (title, year) = (:t, :y)", Movie.class) .setParameter("t", "Jurassic World") .setParameter("y", 2015) .getResultList();for (var m : rowValueResult) { System.out.println("Title: " + m.getTitle());}

Hibernate ORM拡張機能は、コンポーネントの各ペアを個別に比較します。上記の行値述語は、次の $match ステージに変換されます。

{ "$match": { "$and": [ { "title": { "$eq": "Jurassic World" } }, { "year": { "$eq": 2015 } } ] }}

<> 演算子を使用する行値述語は、$nor 式でラップされた同じ $and 式に変換されます。

フィールドを別のフィールドのリストと比較する場合(where (title1, year1) = (title2, year2)など)、Hibernate ORM拡張機能は述語を$expr式に変換します。

SELECT 句で、行値述語を使用できます。述語は、プロジェクション内のブール値に評価されます。

注意

Null セマンティクス

行値プレディケートは、Hibernate ORM の三値論理ではなく、MongoDB クエリ言語の null セマンティクスに従います。したがって、<> プレディケートは、コンポーネントが null または存在しないドキュメントと一致します。学ぶには、このガイドのフィールド値と Null の比較セクションを参照してください。

1 行のフィールドを複数行の値と照合するには、IN 演算子を使用します。次の例では、2 つの title と year のペアのいずれかに一致するドキュメントを検索します。

var rowValueInResult = session.createQuery( "from Movie where (title, year) in (('Jurassic World', 2015), ('Ex Machina', 2015))", Movie.class) .getResultList();for (var m : rowValueInResult) { System.out.println("Title: " + m.getTitle());}

上記の行値述語は、次の $match ステージに変換されます。

{ "$match": { "$or": [ { "$and": [ { "title": { "$eq": "Jurassic World" } }, { "year": { "$eq": 2015 } } ] }, { "$and": [ { "title": { "$eq": "Ex Machina" } }, { "year": { "$eq": 2015 } } ] } ] }}

リストに値が1行しか含まれていない場合、述語は $and 式のみに変換されます。NOT IN 述語は、$nor 式でラップされた $or 式に変換されます。

重要

順序の比較

Hibernate ORM 拡張機能は、>、>=、<、または <= 演算子を使用する行値述語をサポートしていません。これらの述語により、Hibernate ORM 拡張機能は FeatureNotSupportedException をスローします。

比較演算子を使用してフィールドを null と比較する場合、Hibernate ORM 拡張機能は、Hibernate ORM が定義する三項論理ではなく、MongoDB クエリ言語の null セマンティクスを適用します。

注意

nullに対するHibernateの3値論理

Hibernate ORM v6.3以降では、nullとの比較はnullとして評価され、述語はこれをfalseとして扱います。Hibernate ORM拡張機能は、この動作を実装していません。Hibernate ORM拡張機能がサポートする機能の詳細については、「機能の互換性」ページのデータ型のサポートを参照してください。

MongoDB 比較演算子は、フィールドがない場合と明示的な null 値を保存するフィールドの両方を評価して null とします。その結果、= null 比較は、フィールドに null が保存されているドキュメントおよびフィールドが存在しないドキュメントと一致します。<> null または != null 比較は、フィールドに別の値が保存されているドキュメントを検索します。

次の例では、= 演算子を使用して、sample_mflix.movies コレクションから null または欠落している cast 値を持つドキュメントを検索します。

var nullComparisonResult = session.createQuery("from Movie where cast = null", Movie.class) .getResultList();for (var m : nullComparisonResult) { System.out.println("Title: " + m.getTitle());}

Hibernate ORM拡張機能は、このクエリを次の$matchステージに変換します。

{ "$match": { "cast": { "$eq": null } }}

>、>=、<、および<=演算子を使用する比較では、存在しないフィールドに対してMongoDB BSON比較順序に従います。nullは独自のBSON型であるため、>= nullまたは<= nullの比較は、フィールドがnullを保存しているか、または欠落しているドキュメントと一致します。> nullまたは< nullの比較は、どのドキュメントとも一致しません。

比較演算子の代わりに述語を使用して null と欠損値を照合する方法については、このガイドの IS NULL セクションと IS NOT NULL セクションを参照してください。

フィールド値、リテラル、クエリパラメータから値を計算できます。その値を SELECT 句で返したり、WHERE 句で比較したりできます。Hibernate ORM拡張機能は、計算された式をMongoDB集計式に変換します。

Hibernate ORM拡張機能は、計算式において以下の演算子をサポートしています。

  • +: 加算。これは以下のように変換されます。 $add

  • -: 減算。これは次のように変換されます。 $subtract

  • *: 乗算は、つまり $multiply

  • /: Division。これは次のように翻訳されます。 $divide

  • 単項 - および +

注意

除算は常に整数を返す

Hibernate ORMは、MongoDB集計パイプラインでの除算をMongoDBの$divide演算子に変換します。この演算子は常にdoubleを返します。Hibernate ORM拡張機能は、$divideを$toIntでラップして結果を切り捨てます。結果の型がBIGINTの場合は$toLongでラップします。この動作は、Hibernate ORMのPORTABLE_INTEGER_DIVISION設定を有効にしているかどうかに関係なく、/演算子とCriteria APIのquot()メソッドに適用されます。

div 演算子はサポートされていません。

また、計算式内で比較演算子の使用セクションで説明されている比較演算子を使用することもできます。

重要

オペランドの制限

計算式のオペランドは、フィールド参照、リテラル、またはクエリパラメータである必要があります。Hibernate ORM拡張機能は、オペランドとしての関数呼び出しをサポートしていません。

Hibernate ORMはHQLの%演算子をmod()関数呼び出しに書き換えるため、%もサポートされていません。剰余演算を実行するには、Criteria APIのCriteriaBuilder.mod()メソッドを使用します。これはMongoDBの$mod演算子に変換されます。

Criteria APIのCriteriaBuilder.quot()メソッドは、/演算子とまったく同じように動作します。

計算された式を選択すると、Hibernate ORM拡張機能は計算された値を$projectステージに追加します。ASキーワードを使用して式にエイリアスを割り当てると、Hibernate ORM拡張機能はそのエイリアスをプロジェクションキーとして使用します。それ以外の場合は、#c_<n>の形式でキーを生成します。

次の例では、year フィールドの値をクエリパラメータから減算することで、sample_mflix.movies コレクション内の各 "Hairspray" 映画の年齢を計算します。

var arithmeticResult = session.createQuery( "select title, :currentYear - year as age from Movie where title = :title", Object[].class) .setParameter("currentYear", 2026) .setParameter("title", "Hairspray") .getResultList();for (var row : arithmeticResult) { System.out.println("Title: " + row[0] + ", Age: " + row[1]);}

Hibernate ORM 拡張機能は、前述の計算された式を次の $project ステージに変換します。

{ "$project": { "title": true, "age": { "$subtract": [ 2026, "$year" ] }, "_id": 0 }}

WHERE 句では、計算された式を値と比較したり、2 つのフィールド値を相互に比較したりできます。比較のいずれかの側が直接的なフィールド参照や値ではない場合、Hibernate ORM 拡張機能は比較を MongoDB の $expr 演算子でラップします。フィールドと値の比較では、引き続きコンパクトな { field: { operator: value } } 形式が使用されます。

次の例では、2026より 20 年以上前に公開された "Hairspray" 本の映画を検索します。

var computedFilterResult = session.createQuery( "from Movie where title = :title and :currentYear - year < 20", Movie.class) .setParameter("title", "Hairspray") .setParameter("currentYear", 2026) .getResultList();for (var m : computedFilterResult) { System.out.println("Title: " + m.getTitle() + ", Year: " + m.getYear());}

Hibernate ORM拡張機能は、前のクエリを次の$matchステージに変換します。このステージでは、title比較はコンパクト形式を使用し、計算された比較は$exprを使用します。

{ "$match": { "$and": [ { "title": { "$eq": "Hairspray" } }, { "$expr": { "$lt": [ { "$subtract": [ 2026, "$year" ] }, 20 ] } } ] }}

SELECT ステートメントで比較を使用して、比較をフィルターとして使用する代わりに、そのブール値の結果を返すことができます。

次の例では、各 "Hairspray" 映画のタイトルと、その映画が 2000 以降に公開されたかどうかを返します。

var comparisonResult = session.createQuery( "select title, year > 2000 as isRecent from Movie where title = :title", Object[].class) .setParameter("title", "Hairspray") .getResultList();for (var row : comparisonResult) { System.out.println("Title: " + row[0] + ", Recent: " + row[1]);}

Hibernate ORM 拡張機能は、前述の比較を次の $project ステージに変換します。

{ "$project": { "title": true, "isRecent": { "$gt": [ "$year", 2000 ] }, "_id": 0 }}

CASE 式は、指定した条件ごとに異なる値を返します。Hibernate ORM 拡張機能は、HQL と JPQL の両方の単純な CASE 式と検索された 式をサポートしています。

  • 単純なケース: CASE キーワードの後の式が、各 WHEN 句の値と等しいかどうかが比較されます。単純なケース式の例は case year when 2000 then 'Modern' else 'Classic' end です。

  • 検索されたケース: 各 WHEN 句は述語を指定します。検索された case 式の例は case when year > 2000 then 'Modern' else 'Classic' end です。

Hibernate ORM拡張機能は、CASE式をMongoDBの$switch演算子に変換します。この演算子は、各WHEN句のブランチを作成し、指定した順序でブランチを評価します。ELSE句は、$switchのdefault値になります。ELSE句を省略した場合、一致するブランチがないと式はnullを返します。

CASE 式は計算された式を返すことができ、CASE 式は次の位置で使用できます。

  • 次の例に示すような SELECT 句。

  • WHERE句内の比較のオペランド。Hibernate ORM拡張機能は、これをMongoDBの$expr演算子でラップします。

  • 一括更新ステートメントの SET 句。例については、「CRUD 操作」ガイドの「条件付きロジックに基づく複数更新の例」セクションを参照してください。

次の例では、各 "Hairspray" 映画のタイトルと、映画の year 値に応じたラベルを返します。

var caseResult = session.createQuery( "select title, case when year > 2000 then 'Modern' else 'Classic' end as era " + "from Movie where title = :title", Object[].class) .setParameter("title", "Hairspray") .getResultList();for (var row : caseResult) { System.out.println("Title: " + row[0] + ", Era: " + row[1]);}

Hibernate ORM拡張機能は、前述のCASE式を次の$projectステージに変換します。

{ "$project": { "title": true, "era": { "$switch": { "branches": [ { "case": { "$gt": [ "$year", 2000 ] }, "then": "Modern" } ], "default": "Classic" } }, "_id": 0 }}

重要

CASE式の制限

CASE式はMongoDBの集計式を生成するため、フィールド参照やリテラル値が必要な場所で使用することはできません。CASE式を使用すると、Hibernate ORM拡張機能はFeatureNotSupportedExceptionを発生させます。

  • ORDER BY 句内(ただし、同じ CASE 式が GROUP BY キーである場合を除く)。

  • LIKE 述語の照合式として。

  • IN または IS NULL 述語のテスト式として。

  • オペランドではなく、WHERE 句の述語として使用します。

Hibernate ORM拡張機能は、クエリステートメントで以下の述語比較演算子をサポートしています。

注意

Hibernate ORM拡張機能は、すべての比較演算子をサポートしているわけではありません。サポートの制限を学ぶには、「機能互換性」ページの「クエリサポート」を参照してください。

EXISTS 述語は、特定のフィールドを持つドキュメントと一致し、一致する配列要素の数に関係なく、一致する親ドキュメントごとに 1 つの結果のみを返します。

注意

EXISTSサブクエリの制限

Hibernate ORM拡張機能は、親エンティティの配列フィールドに対するEXISTSサブクエリのみをサポートしており、WHERE句でのみ使用できます。Hibernate ORM拡張機能は、次のEXISTSサブクエリをサポートしていません。

  • フィールドを最初に指定せずにエンティティに対してクエリを実行する

  • 同じ親ドキュメント内のフィールドを比較する

  • SELECT 句に記述する

全体の例については、このガイドの 埋め込み配列の要素に対するクエリ セクションを参照してください。

BETWEEN 述語は、指定された範囲内のフィールド値を持つドキュメントと一致します。

以下の例では、BETWEEN 述語を使用して、sample_mflix.movies コレクションから 2012 以上 2013 以下の year 値を持つドキュメントを検索します。

var betweenResult = session.createQuery("from Movie where year between :start and :end", Movie.class) .setParameter("start", 2012) .setParameter("end", 2013) .getResultList();for (var m : betweenResult) { System.out.println("Title: " + m.getTitle());}

Hibernate ORM拡張機能は、前述の BETWEEN 述語を次の $match ステージに変換します。

{ "$match": { "year": { "$gte": 2012, "$lte": 2013 } }}

IN 述語は、フィールド値が指定されたリスト内のいずれかの値と等しいドキュメントと一致します。リスト値は、リテラル、名前付きパラメータ、または位置パラメータとして指定できます。

次の例では、IN 述語を使用して、sample_mflix.movies コレクションから year 値が 1994 または 1996 であるドキュメントを検索します。

var inResult = session.createQuery("from Movie where year in (:first, :second)", Movie.class) .setParameter("first", 1994) .setParameter("second", 1996) .getResultList();for (var m : inResult) { System.out.println("Title: " + m.getTitle());}

Hibernate ORM拡張機能は、前述の IN 述語を次の $match ステージに変換します。

{ "$match": { "year": { "$in": [ 1994, 1996 ] } }}

空のリストは有効ですが、どのドキュメントともマッチングすることはありません。例として、year in () はドキュメントに一致しません。

注意

IN 述語の制限

Hibernate ORM拡張機能は、INの左側の値がフィールドパスである場合にのみ、IN述語をサポートします。Hibernate ORM拡張機能は、次のIN述語をサポートしていません。

  • サブクエリを値のリストとして受け取ります。

  • :value in m.cast のように、配列値の式に対して値をテストします。配列フィールドに対して値を照合するには、代わりに array_contains() 関数を使用します。

配列のクエリについてさらに学ぶには、このガイドの「配列フィールドのクエリ」セクションを参照してください。

NOT IN 述語は、フィールド値が指定されたリスト内のどの値とも一致しないドキュメントと一致します。NOT IN は、IN 述語と同じリスト形式を受け入れ、同じ制限があります。

次の例では、NOT IN述語を使用して、sample_mflix.moviesコレクションから"Romeo and Juliet"または"Best in Show"以外のtitle値を持つドキュメントを検索します。NOT INはリストされた値のみを除外するため、この例ではsetMaxResults()メソッドを呼び出して、結果セットを10個のドキュメントに制限しています。

var notInResult = session.createQuery("from Movie where title not in (:first, :second)", Movie.class) .setParameter("first", "Romeo and Juliet") .setParameter("second", "Best in Show") .setMaxResults(10) .getResultList();for (var m : notInResult) { System.out.println("Title: " + m.getTitle());}

Hibernate ORM拡張機能は、前述の NOT IN 述語を次の $match ステージに変換します。

{ "$match": { "title": { "$nin": [ "Romeo and Juliet", "Best in Show" ] } }}

$nin は空の値のリストと比較してすべてのドキュメントと一致するため、title not in () はすべてのドキュメントと一致します。

注意

NOT IN の制限

Hibernate ORM拡張機能は、NOT INの左側の値がフィールドパスである場合にのみ、NOT IN述語をサポートします。Hibernate ORM拡張機能は、次のNOT IN述語をサポートしていません。

  • サブクエリを値のリストとして受け取ります。

  • 配列値式に対して値をテストします。:value not in m.castのように。

注意

Null セマンティクス

行値プレディケートは、Hibernate ORM の三値論理ではなく、MongoDB クエリ言語の null セマンティクスに従います。したがって、NOT IN プレディケートは、コンポーネントが null または存在しないドキュメントと一致します。学ぶには、このガイドのフィールド値と Null の比較セクションを参照してください。

IS NULL 述語は、null または欠落している値を持つ特定のフィールドを持つドキュメントと一致します。

述語の代わりに比較演算子を使用してフィールドを null と比較する方法については、このガイドの「フィールド値と Null の比較」セクションを参照してください。

次の例では、IS NULL 述語を使用して、sample_mflix.movies コレクションから null cast 値が欠落しているか、またはその値を持つドキュメントを検索します。

var isNullResult = session.createQuery("from Movie where cast is null", Movie.class) .getResultList();for (var m : isNullResult) { System.out.println("Title: " + m.getTitle());}

Hibernate ORM 拡張機能は、前述の IS NULL 述語を、フィールドが明示的に null であるか、またはフィールドがないドキュメントを照合する次の $match ステージに翻訳します:

{ "$match": { "cast": { "$eq": null } }}

IS NOT NULL 述語は、null ではない、または欠落していない値を持つフィールドを持つドキュメントと一致します。

次の例では、IS NOT NULL 述語を使用して、sample_mflix.movies コレクションから directors 値を持つドキュメントを検索します。

var isNotNullResult = session.createQuery("from Movie where directors is not null", Movie.class) .getResultList();for (var m : isNotNullResult) { System.out.println("Title: " + m.getTitle());}

Hibernate ORM 拡張機能は、前述の IS NOT NULL 条件式を次の $match ステージに翻訳します。このステージは、フィールドが存在し、明示的に null でないドキュメントと一致します。

{ "$match": { "directors": { "$ne": null } }}

LIKE 述語は大文字と小文字を区別し、フィールド値が指定されたパスワードなしと一致するドキュメントを検索します。パスワードなしはフィールドの値全体にマッチします。また、次のワイルドカード文字を使用できます。

  • %: 0文字以上に一致します。

  • _: 正確に1文字に一致します。

プレフィックスに一致させるにはパスワードなしの末尾に % を含め、サフィックスに一致させるにはパスワードなしの先頭に % を含めます。

Tip

ワイルドカード文字のエスケープ

% または _ をリテラル文字として一致させる場合は、ESCAPE クローズを使用します。例として、title like '100!%' escape '!' は値 "100%" と一致します。ESCAPE を %、_、またはエスケープ文字自体と一緒に使用できます。もしこれを他の文字と一緒に使用するか、またはパスワードなしの末尾に置いたままにすると、Hibernate ORM 拡張機能は IllegalArgumentException をスローします。

次の例では、LIKE 述語を使用して、title 値が "W" で始まり、その後に任意の 1 文字が続き、その後に "r" が続くドキュメントを sample_mflix.movies コレクションから検索します。

var likeResult = session.createQuery("from Movie where title like 'W_r%'", Movie.class) .getResultList();for (var m : likeResult) { System.out.println("Title: " + m.getTitle());}

Hibernate ORM拡張機能は、前述の LIKE 述語を次の $match ステージに変換します。

{ "$match": { "title": { "$regex": /^W.r.*$/s } }}

注意

LIKE 述語の制限

LIKE と比較する値は、'%War%' のような string リテラルである必要があります。Hibernate ORM 拡張機能は、パスワードなしに対するバインドパラメータ (like :pattern)、別のフィールド (like m.plot)、または計算値 (like concat('War', '%')) をサポートしておらず、それらを使用すると FeatureNotSupportedException がスローされます。

HQL LIKE 述語について学ぶには、Hibernate ORM ドキュメントの「クエリ言語へのガイド」を参照してください。

NOT LIKE述語は、フィールド値が指定されたパスワードなしと一致しないドキュメントと一致します。Hibernate ORM拡張機能は、LIKE述語が生成する$regexフィルターを否定し、LIKE述語と同じパターンマッチング動作と制限を使用します。

以下の例では、NOT LIKE 述語を使用して、sample_mflix.movies コレクションから "The" で始まらない title 値を持つドキュメントを検索します。プレディケートがほとんどのドキュメントにマッチするため、例では setMaxResults() メソッドを呼び出して、結果セットを 5 ドキュメントに制限します。

var notLikeResult = session.createQuery("from Movie where title not like 'The%'", Movie.class) .setMaxResults(5) .getResultList();for (var m : notLikeResult) { System.out.println("Title: " + m.getTitle());}

Hibernate ORM拡張機能は、前述の NOT LIKE 述語を次の $match ステージに変換します。

{ "$match": { "$nor": [ { "title": { "$regex": /^The.*$/s } } ] }}

ILIKE 述語は、LIKE 述語の大文字と小文字を区別しない形式です。Hibernate ORM 拡張機能は、LIKE 述語が生成する $regex フィルターを大文字と小文字を区別しないものとしてマークし、LIKE 述語と同じパスワードなしマッチング動作と制限を使用します。

次の例では、ILIKE 述語を使用して、"Star" を含む title 値を持つドキュメントを sample_mflix.movies コレクションから検索します。

var ilikeResult = session.createQuery("from Movie where title ilike '%Star%'", Movie.class) .getResultList();for (var m : ilikeResult) { System.out.println("Title: " + m.getTitle());}

Hibernate ORM拡張機能は、前述の ILIKE 述語を次の $match ステージに変換します。

{ "$match": { "title": { "$regex": /^.*Star.*$/is } }}

NOT ILIKE 述語は、NOT LIKE 述語の大文字と小文字を区別しない形式です。Hibernate ORM 拡張機能は、ILIKE 述語が生成する大文字と小文字を区別しない $regex フィルターを否定し、LIKE 述語と同じパスワードなしマッチング動作と制限を使用します。

次の例では、NOT ILIKE述語を使用して、title値に"The"が含まれていないドキュメントをsample_mflix.moviesコレクションから検索します。述語はほとんどのドキュメントに一致するため、この例ではsetMaxResults()メソッドを呼び出して、結果セットを5つのドキュメントに制限しています。

var notIlikeResult = session.createQuery("from Movie where title not ilike '%The%'", Movie.class) .setMaxResults(5) .getResultList();for (var m : notIlikeResult) { System.out.println("Title: " + m.getTitle());}

Hibernate ORM拡張機能は、前述の NOT ILIKE 述語を次の $match ステージに変換します。

{ "$match": { "$nor": [ { "title": { "$regex": /^.*The.*$/is } } ] }}

クエリ ステートメントでは次の演算子を使用して、複数のクエリ条件を組み合わせることができます。

  • and: すべての条件に一致する

  • or: 任意の条件に一致します

  • not: 一致基準に一致しません

次の例では、 sample_mflix.moviesコレクションから、title 値が "The Godfather" で、かつ year 値が 1972 であるドキュメントを検索します。

var logicalResult = session.createQuery("from Movie where title = :t and year = :y", Movie.class) .setParameter("t", "The Godfather") .setParameter("y", 1972) .getSingleResult();System.out.println("Title: " + logicalResult.getTitle());

ObjectId 値に基づいてドキュメントを検索するには、セッションを使用している場合はこの値を get() メソッドに渡します。また、エンティティ マネージャーを使用している場合は find() メソッドに引数として渡します。 。

次の例では、sample_mflix.moviesコレクションからドキュメントをObjectId値で検索する。

var movieById = session.get(Movie.class, new ObjectId("573a13a8f29313caabd1d53c"));

@Struct集約埋め込み可能オブジェクトを作成することで、MongoDBの埋め込みドキュメントを表現できます。その後、Hibernate ORM拡張機能を使用して、特定の親エンティティに関連付けられた@Struct集約埋め込み可能オブジェクトをフェッチできます。

Tip

埋め込みドキュメントの表現の詳細については、 エンティティの作成ガイドの「埋め込みデータ」を参照してください。

次の例では、sample_mflix.moviesコレクションから title 値が "Hairspray" であるドキュメントを検索します。次に、コードは Awards @Struct 集計埋め込み可能を保存する awardsフィールドを取得し、Awards 埋め込み可能型の winsフィールドを出力します。

var embeddedResult = session.createQuery("select awards from Movie where title = :title", Awards.class) .setParameter("title", "Hairspray") .getResultList();for (var a : embeddedResult) { System.out.println("Award wins: " + a.getWins());}

HQLまたはJPQLクエリのSELECT、WHERE、ORDER BY、およびUPDATE句でドット付きパス式を使用することで、埋め込み可能な型のフィールドを参照できます。また、パス式で複数の埋め込み可能な名前を連結して、別の埋め込み可能な型内のネストされた埋め込み可能な型のフィールドを参照することもできます。

重要

クエリの制限

パス式は、@ColumnTransformerアノテーションを使用してカスタム読み取り式を定義する埋め込み可能なフィールドをサポートしていません。

Hibernate ORM 拡張機能は、エンティティモデルをビルドする際に、次の @Struct 集計埋め込みマッピングも拒否します。

  • @Id フィールドとして使用される @Struct 集計埋め込み可能オブジェクト

  • ポリモーフィックな @Struct 集計埋め込み可能階層

これらの型では、パス式を使用してフィールドを参照することはできません。

次の例では、パス式を使用して sample_mflix.movies コレクション内のドキュメントをフィルターします。sample_mflix.movies コレクションには "Hairspray" 本の映画があります。"Hairspray" 本の映画は 1998 のもので、もう 1 本は 2007 のものです。このクエリは、title 値が "Hairspray" で、awards.wins 値が 10 より大きいドキュメントと一致します。

var matchingDocument = session.createQuery("from Movie where title = :title and awards.wins > :minWins", Movie.class) .setParameter("title", "Hairspray") .setParameter("minWins", 10) .getResultList();for (var m : matchingDocument) { System.out.println("Title: " + m.getTitle() + ", Year: " + m.getYear());}

エンティティのフィールドに @Struct 集約埋め込みの配列が保存されている場合、EXISTS サブクエリを使用して、その配列の少なくとも1つの要素が基準を満たす親ドキュメントを照合できます。Hibernate ORM拡張機能は、サブクエリをMongoDBの $elemMatch 演算子に変換します。この演算子は、すべての基準を同じ配列要素に適用します。

注意

このセクションでは、sample_restaurants データベースを使用します

このセクションの例では、このガイドの他の場所で使用されている sample_mflix.movies コレクションではなく、sample_restaurants.restaurants コレクションを使用します。

これらの例を実行するには、接続文字列の sample_restaurants データベースに接続します。sample_restaurants データベースについて詳しく学ぶには、Atlas サンプル データセットを参照してください。

次の Restaurant エンティティは restaurants コレクションにマッピングされ、Grade embeddables のリストを grades フィールドに保存します。

package org.example; import com.mongodb.hibernate.annotations.ObjectIdGenerator;import jakarta.persistence.Column;import org.bson.types.ObjectId;import java.util.List; import jakarta.persistence.Entity;import jakarta.persistence.Id;import jakarta.persistence.Table; @Entity@Table(name = "restaurants")public class Restaurant { @Id @ObjectIdGenerator @Column(name = "_id") private ObjectId id; private String name; private String borough; private List<Grade> grades; public Restaurant(String name, String borough, List<Grade> grades) { this.name = name; this.borough = borough; this.grades = grades; } public Restaurant() { } public ObjectId getId() { return id; } public void setId(ObjectId id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getBorough() { return borough; } public void setBorough(String borough) { this.borough = borough; } public List<Grade> getGrades() { return grades; } public void setGrades(List<Grade> grades) { this.grades = grades; } }

次の Grade @Struct 集計型の埋め込み可能なオブジェクトは、grades 配列の各要素を表します:

package org.example;import jakarta.persistence.*;import org.hibernate.annotations.Struct; @Embeddable@Struct(name = "Grade")public class Grade { private String grade; private int score; public Grade() { } public Grade(String grade, int score) { this.grade = grade; this.score = score; } public String getGrade() { return grade; } public void setGrade(String grade) { this.grade = grade; } public int getScore() { return score; } public void setScore(int score) { this.score = score; } }

Tip

配列の詳細を学ぶには、埋め込み可能なについては、「エンティティの作成」ガイドの「埋め込みデータ」を参照してください。

restaurants コレクションのドキュメントには次のようなものがあります。

{ "_id": { "$oid": "5eb3d668b31de5d588f4292a" }, "name": "Morris Park Bake Shop", "borough": "Bronx", "cuisine": "Bakery", "grades": [ { "date": { "$date": 1393804800000 }, "grade": "A", "score": 2 }, { "date": { "$date": 1299715200000 }, "grade": "B", "score": 14 } ]}

次の例では、grades 配列要素の grade 値が "B" で、score 値が 12 と等しいレストランを検索します。両方の条件が同じサブクエリに現れるため、同じ配列要素と一致する必要があります。

var existsResult = session.createQuery( "from Restaurant r where exists (select g.grade from r.grades g where g.grade = :grade and g.score = :score)", Restaurant.class) .setParameter("grade", "B") .setParameter("score", 12) .getResultList();for (var r : existsResult) { System.out.println("Name: " + r.getName());}

Hibernate ORM拡張機能は、前述の EXISTS サブクエリを次の $match ステージに変換します。

{ "$match": { "grades": { "$elemMatch": { "grade": { "$eq": "B" }, "score": { "$eq": 12 } } } }}

Hibernetes ORM 拡張機能は、配列フィールドをクエリするための次の関数をサポートしています。

  • array_contains(): 配列フィールドに指定された値が含まれるドキュメントの一致

  • array_contains_nullable(): 配列フィールドに null 値を含む指定された値が含まれるドキュメントの一致

  • array_includes(): 配列フィールドに別の配列値が含まれるドキュメントの一致

  • array_includes_nullable(): 配列フィールドに、null 値を含む別の配列値が含まれるドキュメントの一致

Tip

配列関数の詳細については、 Hibernetes ORM ユーザーガイドの 配列を処理するための関数 を参照してください。

次の例では、array_contains() 関数を使用して、sample_mflix.moviesコレクションから cast 配列フィールドに値 "Kathryn Hahn" を持つドキュメントを検索する。

var arrayResult = session.createQuery("from Movie where array_contains(cast, :actor)", Movie.class) .setParameter("actor", "Kathryn Hahn") .getResultList();for (var m : arrayResult) { System.out.println("Title: " + m.getTitle());}

HQL および JPQL クエリで集計関数を使用してクエリ結果をグループ化および要約したり、HAVING 句を使用してグループ化された結果をフィルターしたりできます。HQL および JPQL は、次の集計関数をサポートしています。

  • count()

  • sum()

  • avg()

  • min()

  • max()

注意

GROUP BYの要件

集計関数には GROUP BY クローズが必要です。結果をグループ化せずに集計関数を使用するクエリ(select count(*) from Movie など)はまだサポートされていません。SELECT 節の集計でないフィールドは、GROUP BY 節にも必ず含まれる必要があります。

次の例では、1920年から1924年の間に公開された映画を年ごとにグループ化します。年ごとに、映画の数と全映画の合計実行時間を返します。HAVING句には、合計実行時間が300分を超える映画がある年のみが含まれ、結果は年順に並べ替えられます。

var aggregateResult = session.createQuery( "select year, count(*), sum(runtime) from Movie where year between 1920 and 1924 " + "group by year having sum(runtime) > 300 order by year", Object[].class) .getResultList();for (var row : aggregateResult) { System.out.println("Year: " + row[0] + ", Count: " + row[1] + ", Total runtime: " + row[2]);}

フィールドの重複しない値のみを要約するには、集計関数内に distinct キーワードを含めます。distinct は、count()、sum()、avg()、min()、および max() 集計関数で使用できます。

count(distinct x) null値を無視するため、xのnull以外の個別の値のみをカウントします。min()およびmax()の場合、distinctキーワードは結果を変更しません。

次の例では、1998年から2000年の間に公開された映画を年ごとにグループ化します。年ごとに、映画の数と異なるタイトルの数を返し、結果を年順に並べ替えます。

var distinctResult = session.createQuery( "select year, count(*), count(distinct title) from Movie where year between 1998 and 2000 " + "group by year order by year", Object[].class) .getResultList();for (var row : distinctResult) { System.out.println("Year: " + row[0] + ", Count: " + row[1] + ", Distinct titles: " + row[2]);}

MongoDBデータに対してその他の操作を行う方法の詳細については、CRUD 操作ガイドを参照してください。

関連によってリンクされているエンティティ間でクエリを実行する方法を学ぶには、コレクション間でのエンティティの結合ガイドを参照してください。

datetime 値の一部を返す方法や、datetime 値を string としてレンダーする方法を学ぶには、「クエリでの datetime 関数の使用」ガイドをご覧ください。

HQL と JQL を使用してクエリを実行する方法の詳細については、非表示の ORM ドキュメントの「非表示のクエリ言語へのガイド」を参照してください。

このページを評価