Overview
In this guide, you can learn how to use the MongoDB Extension for Hibernate ORM to run native queries on your MongoDB database. Instead of Hibernate Query Language (HQL) or Jakarta Persistence Query Language (JPQL), native queries allow you to use MongoDB Query Language (MQL) to specify your query. MQL is a query syntax designed for interacting with MongoDB's document-based model.
Tip
MongoDB Query Language
To learn more about MQL's syntax and functionality, see MongoDB Query Language Reference in the MongoDB Server manual.
Hibernate ORM's createQuery() method does not support some MongoDB query features. The createNativeQuery() method allows you to specify database queries in MQL and bypass some operational limitations of the Hibernate ORM extension.
You can also run queries directly on your MongoClient object for expanded query functionality.
Sample Data
The examples in this guide use the Movie entity, which represents the sample_mflix.movies collection from the Atlas sample datasets. The Movie entity has the following definition:
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; public Movie(String title, String plot, int year, int runtime, List<String> cast) { this.title = title; this.plot = plot; this.year = year; this.runtime = runtime; this.cast = cast; } 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; } }
To learn how to create a Java application that uses the MongoDB Extension for Hibernate ORM to interact with this MongoDB sample collection, see the Get Started tutorial.
Note
Persistence Contexts
To enable Hibernate ORM to interact with the database, you must run operations inside a persistence context by using a Hibernate Session or a Jakarta Persistence EntityManager. The examples in this guide use a Session. To learn more about persistence contexts, see the Transactions and Sessions guide.
Run Native Queries
To run a native MongoDB query, specify a MongoDB Query Language (MQL) statement that includes the collection to query and your query criteria in an aggregation pipeline.
Tip
Aggregation Pipeline
To learn more about constructing aggregation pipelines and running aggregation operations, see the Aggregation Pipeline reference in the MongoDB Server manual.
MQL statements have the following format:
String mqlSyntax = """ { aggregate: "<collection to query>", pipeline: [ <aggregation pipeline stages> ] } """;
Important
$project Stage Requirements
The aggregation pipeline in your MQL statement must include a $project stage. To return the query documents as entity instances, you must specify each entity field other than the primary key field in the $project stage.
Then, pass the MQL statement to the createNativeQuery() method. You cannot run native queries that use parameter values. Instead, specify your search terms within the MQL statement.
You can use native queries to perform the following operations:
Filter and Sort Document Fields
This example runs a native query on the sample_mflix.movies collection by passing an MQL statement to the createNativeQuery() method. The code specifies the following aggregation pipeline stages:
$match: Filters for documents that have a title field value of"The Parent Trap"$sort: Sorts the matching documents by theiryearfields in descending order$project: Returns each document field defined in theMovieentity
String nativeQuery = """ { aggregate: "movies", pipeline: [ { $match: { title: { $eq: "The Parent Trap" } } }, { $sort: { year: -1 } }, { $project: { 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()); }
Use Arithmetic Operators
The Hibernate ORM extension does not currently support HQL or JPQL statements that use arithmetic operators. However, you can perform arithmetic operations on your data by using MongoDB's arithmetic operators in an MQL statement.
Tip
Arithmetic Operators
To learn more about Hibernate and MongoDB arithmetic operators, see the following resources:
Numeric arithmetic in the Hibernate ORM query guide
Arithmetic Operators in the MongoDB Server manual
The following example runs a native query on the sample_mflix.movies collection that performs the following actions:
Specifies a
$matchstage to match documents that have ayearvalue greater than2000and aruntimefield that existsSpecifies an
$addFieldsstage to add a new field calledruntimeHoursUses the
$dividearithmetic operator to convert theruntimevalue from minutes to hours for the newruntimeHoursfieldSpecifies a
$projectstage to return each document field defined in theMovieentity, other than the primary key fieldPrints the
titlevalue of each updated document
String nativeQuery = """ { aggregate: "movies", pipeline: [ { $match: { year: { $gt: 2000 }, runtime: { $exists: true } } }, { $addFields: { runtimeHours: { $divide: [ "$runtime", 60 ] } }}, { $project: { 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()); }
Run a MongoDB Search Query
You can run native queries to perform MongoDB Search queries on your database, which are fine-grained text searches on your data. These queries provide advanced search functionality, such as matching text phrases, scoring results for relevance, and highlighting matches.
Important
You cannot run a MongoDB Search query inside a transaction.
To specify a Search query, create a Search index that covers the fields you want to query. Then, pass an aggregation pipeline to your createNativeQuery() method that includes a $search or $searchMeta stage.
Tip
MongoDB Search
To learn more about MongoDB Search queries and indexes, see atlas-search in the MongoDB Server manual.
This example runs a Search query by passing the $search pipeline stage to the createNativeQuery() method. The code performs the following actions:
Specifies the Search index that covers the
plotfield. Ensure that you replace the<indexName>placeholder with your Search index name.Queries for documents whose
plotvalues contain the string"whirlwind romance"with no more than3words between themSpecifies a
$projectstage to return each document field defined in theMovieentity, other than the primary key fieldPrints the
titleandplotvalues of the matching documents
String nativeQuery = """ { aggregate: "movies", pipeline: [ { $search: { index: "<indexName>", phrase: { path: "plot", query: "whirlwind romance", slop: 3 } } }, { $project: { 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()); }
Run MongoClient Operations
If you want to run database operations that neither the createQuery() method nor the createNativeQuery() method supports, you can operate on a MongoClient object directly in your Java application. When working with the MongoClient, you can access the MongoDB Java Sync Driver's functionality.
Tip
Feature Support
To learn more about unsupported MongoDB features that you must use a MongoClient object to access, see the Feature Compatibility page.
To learn how to use the Java driver to interact with MongoDB, see the MongoDB Java Driver documentation.
Create Indexes with the MongoClient
You cannot use the Hibernate ORM extension to create indexes on a collection, but you can instantiate a MongoClient and use the Java driver's createIndex() method. The following code creates a title field index on the sample_mflix.movies collection:
// 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));
To learn more about how to use the Java driver to create indexes, see the Indexes guide in the Java driver documentation.
Additional Information
To learn more about the query languages discussed in this guide, see the following resources:
A Guide to Hibernate Query Language in the Hibernate ORM documentation
MongoDB Query Language Reference in the MongoDB Server manual