Overview
このガイドでは、 Hibernetes ORM 用のMongoDB拡張機能 を使用してMongoDBデータベースでネイティブ クエリを実行する方法を学習します。非表示クエリ言語 (HQL) または Java 永続クエリ言語 (JavaQL) の代わりに、ネイティブ クエリではMongoDBクエリ言語 (MQL) を使用してクエリを指定できます。 MQL は、 MongoDBドキュメントベースのモデルを操作するために設計されたクエリ構文です。
Hibernate ORM の createQuery() メソッドは、一部のMongoDBクエリ機能をサポートしていません。createNativeQuery() メソッドを使用すると、MQLでデータベースクエリを指定し、Hibernate ORM 拡張機能の一部の運用上の制限をバイパスできます。
また、クエリ機能を拡張するために、MongoClientオブジェクトに対してクエリを直接実行することもできます。
サンプル データ
このガイドの例では、AtlasサンプルデータセットのMovie sample_mflix.moviesコレクションを表す エンティティを使用します。Movie エンティティには、次の定義があります。
import com.mongodb.hibernate.annotations.ObjectIdGenerator; import org.bson.types.ObjectId; import java.util.List; import jakarta.persistence.Entity; import jakarta.persistence.Id; import jakarta.persistence.Table; public class Movie { private ObjectId id; private String title; private String plot; private int year; private int runtime; private List<String> cast; private List<String> directors; public Movie(String title, String plot, int year, int runtime, List<String> cast, List<String> directors) { this.title = title; this.plot = plot; this.year = year; this.runtime = runtime; this.cast = cast; this.directors = directors; } 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 int getRuntime() { return runtime; } public void setRuntime(int runtime) { this.runtime = runtime; } 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; } }
Hibernetes ORM 用のMongoDB拡張機能を使用してこのMongoDBサンプルコレクションと交流するJavaアプリケーションを作成する方法については、Get Started チュートリアルを参照してください。
注意
永続性コンテキスト
Hibernate ORM を有効にしてデータベースと交流するには、Hibernate Session または Jakarta 永続性 EntityManager を使用して永続性コンテキスト内で操作を実行する必要があります。このガイドの例では、Session を使用しています。永続性コンテキストの詳細については、トランザクションとセッションのガイドを参照してください。
ネイティブクエリを実行する
ネイティブのMongoDBクエリを実行するには、クエリするコレクションとクエリ条件を集計パイプラインで含むMongoDBクエリ言語(MQL)ステートメントを指定します。
MQLステートメントは次の形式です。
String mqlSyntax = """ { aggregate: "<collection to query>", pipeline: [ <aggregation pipeline stages> ] } """;
重要
$ プロジェクトステージの要件
MQLステートメントの集計パイプラインには ステージが含まれている必要があります。クエリ$project ドキュメントをエンティティ$project インスタンスとして返すには、 フィールドを含む、_id ステージの各エンティティフィールドを指定する必要があります。 Hibernetes ORM 拡張機能はプロジェクトフィールドを返し、省略すると を非表示にします。 を省略するエンティティバウンド クエリは、エンティティ識別子が にマップされているため、 では失敗する可能性があります。識別子を使用したままにするには、プロジェクト_id _idUnknown column label [_id]_id_id: 1をプロジェクトします。
次に、 MQLステートメントを createNativeQuery() メソッドに渡します。
ネイティブクエリを使用して、次の操作を実行できます。
重要
拡張JSONシンタックスが必要
ネイティブ クエリは 拡張JSON v 形式で記述する必要があります。 Hibernetes ORM 拡張機能は、ネイティブ クエリで一重引用符またはMongoDB Server シェル正規式構文(2/pattern/ )をサポートしていません。例、正規式を使用してクエリを実行するには、 ではなく$regularExpression 拡張JSONタイプを使用します。/pattern/
ドキュメント フィールドのフィルターとソート
この例ではMQLステートメントを createNativeQuery() メソッドに渡して、sample_mflix.moviesコレクションに対してネイティブクエリを実行します。このコードでは、次の集計パイプライン ステージを指定します。
$match: タイトルフィールドの値が のドキュメントをフィルター"The Parent Trap"$sort: 一致するドキュメントをyearフィールドで降順に並べ替えます$project:Movieエンティティで定義されている各ドキュメントフィールドを返します
String nativeQuery = """ { aggregate: "movies", pipeline: [ { $match: { title: { $eq: "The Parent Trap" } } }, { $sort: { year: -1 } }, { $project: { _id: 1, title: 1, plot: 1, year: 1, runtime: 1, cast: 1 } } ] } """; var results = session.createNativeQuery(nativeQuery, Movie.class) .getResultList(); for (Movie movie : results) { System.out.println("Title: " + movie.getTitle() + ", Year: " + movie.getYear()); }
算術演算子の使用
注意
ネイティブ クエリは、 Hibernetes ORM 拡張機能 でサポートされていない算術操作に最適です。 Hibernetes ORM 拡張機能がサポートする算術演算子の詳細については、 機能の互換性 ページの「クエリ サポート」セクションを参照してください。
次の例では、 sample_mflix.moviesコレクションに対して次のアクションを実行するネイティブ クエリを実行します。
yearの値が2000より大きく、かつruntimeフィールドが存在するドキュメントを検索するために、$matchステージを指定しますruntimeHoursという新しいフィールドを追加するには$addFieldsステージを指定します$divide算術演算子を使用して、新しいruntimeHoursフィールドのruntime値を 分から時間に変換しますMovieエンティティで定義されている各ドキュメントフィールド(_idフィールドを含む)を返すには、$projectステージを指定します更新された各ドキュメントの
title値を出力します
String nativeQuery = """ { aggregate: "movies", pipeline: [ { $match: { year: { $gt: 2000 }, runtime: { $exists: true } } }, { $addFields: { runtimeHours: { $divide: [ "$runtime", 60 ] } }}, { $project: { _id: 1, title: 1, plot: 1, year: 1, runtime: 1, cast: 1, runtimeHours: 1 }} ] } """; var results = session.createNativeQuery(nativeQuery, Movie.class) .getResultList(); for (Movie result : results) { System.out.println("Added field to movie: " + result.getTitle()); }
MongoDB 検索クエリを実行する
ネイティブ クエリを実行すると、データベースに対してMongoDB 検索クエリを実行することができます。これは、データに対するきめ細かなテキスト検索です。これらのクエリは、テキスト フレーズの一致、関連性の結果のスコアリング、一致の強調表示など、高度な検索機能を提供します。
重要
トランザクション内ではMongoDB 検索クエリを実行できません。
検索クエリを指定するには、クエリを実行するフィールドをカバーする検索インデックスを作成します。次に、$search または $searchMeta ステージを含む集計パイプラインをcreateNativeQuery() メソッドに渡します。
Tip
MongoDB Search
MongoDB Search クエリとインデックスの詳細については、 MongoDB Serverマニュアルの「 MongoDB Search の概要 」を参照してください。
この例では、$searchパイプラインステージをcreateNativeQuery()メソッドに渡して検索クエリを実行します。このコードは、次のアクションを実行します。
plotフィールドをカバーする検索インデックスを指定します。<indexName>プレースホルダーを 検索インデックス名に置き換えてください。plot値に対し、3単語以下の文字列"whirlwind romance"が含まれるドキュメントのクエリMovieエンティティで定義されている各ドキュメントフィールド(_idフィールドを含む)を返すには、$projectステージを指定します一致するドキュメントの
titleとplotの値を出力します
String nativeQuery = """ { aggregate: "movies", pipeline: [ { $search: { index: "<indexName>", phrase: { path: "plot", query: "whirlwind romance", slop: 3 } } }, { $project: { _id: 1, title: 1, plot: 1, year: 1, runtime: 1, cast: 1 } } ] } """; var results = session.createNativeQuery(nativeQuery, Movie.class) .getResultList(); for (Movie result : results) { System.out.println("Title: " + result.getTitle() + ", Plot: " + result.getPlot()); }
ネイティブ クエリでのパラメーターの使用
MQLステートメントで値を指定するには、名前付きパラメーター(:name)または順序付きパラメーター(?1)を使用できます。次の例では、 title パラメータの値を名前付きパラメータまたは順序付けパラメータとして指定し、次に setParameter() でパラメータ値を指定する方法を示しています。
String nativeQuery = """ { aggregate: "movies", pipeline: [ { $match: { title: { $eq: :movieTitle } } }, { $sort: { year: -1 } }, { $project: { _id: 1, title: 1, plot: 1, year: 1, runtime: 1, cast: 1 } } ] } """; var results = session.createNativeQuery(nativeQuery, Movie.class) .setParameter("movieTitle", "The Parent Trap") .getResultList(); for (Movie movie : results) { System.out.println("Title: " + movie.getTitle() + ", Year: " + movie.getYear()); }
String nativeQuery = """ { aggregate: "movies", pipeline: [ { $match: { title: { $eq: ?1 } } }, { $sort: { year: -1 } }, { $project: { _id: 1, title: 1, plot: 1, year: 1, runtime: 1, cast: 1 } } ] } """; var results = session.createNativeQuery(nativeQuery, Movie.class) .setParameter(1, "The Parent Trap") .getResultList(); for (Movie movie : results) { System.out.println("Title: " + movie.getTitle() + ", Year: " + movie.getYear()); }
MongoClient 操作を実行する
createQuery() メソッドも createNativeQuery() メソッドもサポートしていないデータベース操作を実行する場合は、Javaアプリケーションで直接 MongoClient オブジェクトを操作できます。MongoClient を使用すると、 MongoDB Java Sync Driver の 機能にアクセスできます。
Javaドライバーを使ってMongoDBと交流する方法を学ぶには、MongoDB Javaドライバーのドキュメントを参照してください。
MongoClient によるインデックスの作成
Hibernate ORM 拡張機能を使用してコレクションにインデックスを作成することはできませんが、MongoClient をインスタンス化してJavaドライバーの createIndex() メソッドを使用できます。次のコードを使用することで、sample_mflix.moviesコレクションに titleフィールドインデックスが作成されます。
// Replace the <connection URI> placeholder with your MongoDB connection URI String uri = "<connection URI>"; MongoClient mongoClient = MongoClients.create(uri); MongoDatabase db = mongoClient.getDatabase("sample_mflix"); MongoCollection<Document> collection = db.getCollection("movies"); String indexResult = collection.createIndex(Indexes.ascending("title")); System.out.println(String.format("Index created: %s", indexResult));
Javaドライバーを使用してインデックスを作成する方法の詳細については、Javaドライバーのドキュメントのインデックスガイドを参照してください。
詳細情報
このガイドで説明されているクエリ言語の詳細については、次のリソースを参照してください。
非表示 ORM ドキュメントの「非表示クエリ言語のガイド」
MongoDB Serverマニュアルの MongoDBクエリ言語リファレンス