Overview
En esta guía, puedes aprender a utilizar la extensión de MongoDB para Hibernate ORM para especificar una query de base de datos.
Se puede refinar el conjunto de documentos que una query retorna creando un filtro de query. Un filtro de query es una expresión que especifica los criterios de búsqueda que MongoDB usa para emparejar documentos en una operación de lectura o guardado. Para crear filtros de query de MongoDB, utiliza Hibernate Query Language (HQL) o instrucciones Jakarta Persistence Query Language (JPQL).
Tip
Para obtener más información sobre la sintaxis de HQL y JPQL, consulta Una guía sobre Hibernate languaje del query en la documentación de Hibernate ORM.
Nota
Soporte de query
La extensión MongoDB para Hibernate ORM no admite todas las funcionalidades de query de MongoDB y Hibernate. Para obtener más información, consulta Soporte de query en la página de Compatibilidad de funciones.
Datos de muestra
Los ejemplos de esta guía utilizan la entidad Movie, que representa la colección sample_mflix.movies del conjuntos de datos de muestras de Atlas. La entidad Movie tiene la siguiente definición:
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; public class Movie { private ObjectId id; private String title; private String plot; private int year; private List<String> cast; private List<String> directors; private Instant released; private Awards awards; 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; } }
Para aprender a crear una aplicación Java que utilice la extensión MongoDB para Hibernate ORM para interactuar con esta colección de muestra de MongoDB, consulta el tutorial Primeros pasos.
Los ejemplos de código de esta página también utilizan el siguiente agregado incrustable Awards @Struct:
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; } }
Importante
Contextos de Persistencia
Para habilitar que Hibernate ORM interactúe con la base de datos, debe ejecutar operaciones dentro de un contexto de persistencia utilizando un Session de Hibernate o un EntityManager de Jakarta Persistence. Use HQL para definir consultas de sesión y use JPQL para definir consultas de administrador de entidades.
Antes de ejecutar los ejemplos en esta guía, asegúrate de añadir código de contexto de persistencia y gestión de transacciones a tu aplicación que se asemeje al siguiente código:
var sf = HibernateUtil.getSessionFactory(); Session session = sf.openSession(); Transaction tx = session.beginTransaction(); // ... Perform CRUD operations here tx.commit(); session.close(); sf.close();
Para utilizar una sesión, debes crear un archivo HibernateUtil.java que configure un SessionFactory. Para obtener más información, consulta el paso Configura tu aplicación del tutorial Comenzar.
// Replace <persistence unit> with the name of your persistence unit in the persistence.xml file EntityManagerFactory emf = Persistence.createEntityManagerFactory("<persistence unit>"); EntityManager entityManager = entityManagerFactory.createEntityManager(); entityManager.getTransaction().begin(); // ... Perform CRUD operations here entityManager.getTransaction().commit(); entityManager.close(); emf.close;
Para usar un EntityManager, debes crear un archivo persistence.xml que declare una unidad de persistencia. Para aprender más, consulta el Tutorial utilizando APIs estándar JPA en la documentación de Hibernate ORM.
Propiedad de configuración de semántica nula requerida
Antes de crear una instancia SessionFactory, debe establecer la propiedad de configuración com.mongodb.hibernate.semantics.nulls en MQL. Esta propiedad es obligatoria, no tiene un valor predeterminado y actualmente no acepta ningún otro valor. Si omite la propiedad o le asigna otro valor, la extensión Hibernate ORM generará una excepción HibernateException.
Cuando se establece com.mongodb.hibernate.semantics.nulls en MQL, la propiedad declara que el comportamiento relacionado con los valores nulos sigue el lenguaje de consulta de MongoDB (MQL) que produce la extensión ORM de Hibernate durante la traducción, y no la lógica de tres valores definida por la semántica de valores nulos de SQL.
Debido a que la extensión Hibernate ORM no garantiza una traducción específica, los resultados del comportamiento relacionado con valores nulos pueden cambiar entre versiones.
El siguiente ejemplo establece la propiedad com.mongodb.hibernate.semantics.nulls en su archivo hibernate.properties:
com.mongodb.hibernate.semantics.nulls=MQL
Utilice operadores de comparación
Puedes utilizar los siguientes operadores en tus instrucciones de query para comparar los valores de los campos con valores de query especificados:
=: Coincidencia de igualdad<>Coincidencia de desigualdades>: Comparaciones mayores que>=: Comparaciones mayores o iguales<: Comparaciones menores que<=Comparaciones menor o igual que
El siguiente ejemplo recupera documentos que tienen un valor de year mayor o igual a 2015 de la colección sample_mflix.movies:
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()); }
var comparisonResult = entityManager.createQuery("select m from Movie m where m.year >= :y", Movie.class) .setParameter("y", 2015) .getResultList(); for (var m : comparisonResult) { System.out.println("Title: " + m.getTitle()); }
Comparar varios campos a la vez
Un predicado de valor de fila compara una lista de campos entre paréntesis con una lista de valores entre paréntesis en una sola expresión. La extensión Hibernate ORM admite predicados de valor de fila que utilizan los siguientes operadores:
=: Coincidencia de igualdad<>Coincidencia de desigualdadesINyNOT IN: Comparación con una lista de filas de valores
Puede proporcionar los valores como parámetros vinculados o como literales, y cada lista debe contener el mismo número de componentes.
El siguiente ejemplo recupera documentos que tienen un valor title igual a "Jurassic World" y un valor year igual a 2015 de la colección sample_mflix.movies:
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()); }
var rowValueResult = entityManager.createQuery("select m from Movie m where (m.title, m.year) = (:t, :y)", Movie.class) .setParameter("t", "Jurassic World") .setParameter("y", 2015) .getResultList(); for (var m : rowValueResult) { System.out.println("Title: " + m.getTitle()); }
La extensión Hibernate ORM compara cada par de componentes por separado. El predicado de valor de fila anterior se traduce en la siguiente etapa $match:
{ "$match": { "$and": [ { "title": { "$eq": "Jurassic World" } }, { "year": { "$eq": 2015 } } ] } }
Un predicado de valor de fila que utiliza el operador <> se traduce en la misma expresión $and envuelta en una expresión $nor.
Si comparas los campos con otra lista de campos, como en where (title1, year1) = (title2, year2), la extensión ORM de Hibernate traduce el predicado a una expresión $expr en su lugar.
Puedes usar un predicado de valor de fila en una cláusula SELECT. El predicado se evalúa como un valor booleano en la proyección.
Nota
Semántica nula
Los predicados de valor de fila siguen la semántica de valores nulos del lenguaje de consulta de MongoDB en lugar de la lógica ternaria del ORM de Hibernate, por lo que un predicado <> coincide con documentos en los que un componente es nulo o falta. Para obtener más información, consulte la sección «Comparar valores de campo con valores nulos» de esta guía.
Coincidir con una lista de filas de valores
Para comparar una fila de campos con varias filas de valores, utilice el operador IN. El siguiente ejemplo recupera documentos que coinciden con cualquiera de los dos pares title y 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()); }
var rowValueInResult = entityManager.createQuery( "select m from Movie m where (m.title, m.year) in (('Jurassic World', 2015), ('Ex Machina', 2015))", Movie.class) .getResultList(); for (var m : rowValueInResult) { System.out.println("Title: " + m.getTitle()); }
El predicado de valor de fila precedente se traduce en la siguiente etapa $match:
{ "$match": { "$or": [ { "$and": [ { "title": { "$eq": "Jurassic World" } }, { "year": { "$eq": 2015 } } ] }, { "$and": [ { "title": { "$eq": "Ex Machina" } }, { "year": { "$eq": 2015 } } ] } ] } }
Si la lista contiene solo una fila de valores, el predicado se traduce a la expresión $and sola. Un predicado NOT IN se traduce a la expresión $or envuelta en una expresión $nor.
Importante
Comparación de pedidos
La extensión Hibernate ORM no admite predicados de valor de fila que utilicen los operadores >, >=, < o <=. Estos predicados provocan que la extensión Hibernate ORM genere una excepción FeatureNotSupportedException.
Comparar los valores de los campos con valores nulos.
Cuando se compara un campo con null mediante un operador de comparación, la extensión Hibernate ORM aplica la semántica nula del lenguaje de consulta de MongoDB en lugar de la lógica ternaria que define Hibernate ORM.
Nota
Lógica ternaria de Hibernate para nulo
Hibernate ORM v6.3 y posteriormente evalúa una comparación con null como null, que un predicado trata como false. La extensión Hibernate ORM no implementa este comportamiento. Para obtener más información sobre las características que admite la extensión Hibernate ORM, consulte Compatibilidad con tipos de datos en la página Compatibilidad de características.
Los operadores de comparación de MongoDB evalúan tanto un campo faltante como un campo que almacena un valor null explícito con respecto a null. Como resultado, una comparación = null coincide con documentos en los que el campo almacena null y documentos en los que el campo está ausente. Una comparación <> null o != null coincide con documentos en los que el campo almacena cualquier otro valor.
El siguiente ejemplo utiliza el operador = para recuperar documentos que tienen un valor null o un valor cast faltante de la colección sample_mflix.movies:
var nullComparisonResult = session.createQuery("from Movie where cast = null", Movie.class) .getResultList(); for (var m : nullComparisonResult) { System.out.println("Title: " + m.getTitle()); }
var nullComparisonResult = entityManager.createQuery("select m from Movie m where m.cast = null", Movie.class) .getResultList(); for (var m : nullComparisonResult) { System.out.println("Title: " + m.getTitle()); }
La extensión Hibernate ORM traduce esta consulta a la siguiente etapa $match:
{ "$match": { "cast": { "$eq": null } } }
Las comparaciones que utilizan los operadores >, >=, < y <= siguen el orden de comparación BSON de MongoDB para campos inexistentes. Dado que null es un tipo BSON propio, una comparación >= null o <= null coincide con documentos en los que el campo almacena null o está ausente. Una comparación > null o < null no coincide con ningún documento.
Para hacer coincidir null con valores faltantes usando un predicado en lugar de un operador de comparación, consulte las secciones IS NULL e IS NOT NULL de esta guía.
Utilice expresiones calculadas
Puedes calcular un valor a partir de valores de campo, literales y parámetros de consulta. Luego, puedes devolver ese valor en una cláusula SELECT o compararlo en una cláusula WHERE. La extensión Hibernate ORM traduce una expresión calculada a una expresión de agregación de MongoDB.
La extensión Hibernate ORM admite los siguientes operadores aritméticos en expresiones calculadas:
+: Adición, que se traduce como$add-: Resta, que se traduce en$subtract*: Multiplicación, que se traduce en$multiply/: División, que se traduce en$divideUnario
-y+
Nota
La división siempre devuelve un número entero.
El ORM de Hibernate traduce la división en una canalización de agregación de MongoDB al operador $divide de MongoDB, que siempre devuelve un double. La extensión del ORM de Hibernate trunca el resultado envolviendo $divide en $toInt, o en $toLong si el tipo de resultado es BIGINT. Este comportamiento se aplica al operador / y al método quot() de la API de Criteria, independientemente de si se habilita la configuración PORTABLE_INTEGER_DIVISION del ORM de Hibernate.
El operador div no es compatible.
También puede utilizar los operadores de comparación descritos en la sección "Uso de operadores de comparación" dentro de las expresiones calculadas.
Importante
Limitaciones del operando
Un operando de una expresión calculada debe ser una referencia a un campo, un literal o un parámetro de consulta. La extensión Hibernate ORM no admite llamadas a funciones como operandos.
Debido a que Hibernate ORM reescribe el operador % de HQL a una llamada a la función mod(), % tampoco es compatible. Para realizar una operación de módulo, utilice el método CriteriaBuilder.mod() de la API Criteria, que se traduce al operador $mod de MongoDB.
El método CriteriaBuilder.quot() de la API de Criteria se comporta de forma idéntica al operador /.
Realizar operaciones aritméticas en una proyección
Al seleccionar una expresión calculada, la extensión Hibernate ORM agrega el valor calculado a la etapa $project. Si se le asigna un alias a la expresión mediante la palabra clave AS, la extensión Hibernate ORM utiliza dicho alias como clave de proyección. De lo contrario, genera una clave con el formato #c_<n>.
El siguiente ejemplo calcula la edad de cada película "Hairspray" en la colección sample_mflix.movies restando el valor del campo year de un parámetro de consulta:
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]); }
var arithmeticResult = entityManager.createQuery( "select m.title, :currentYear - m.year as age from Movie m where m.title = :title", Object[].class) .setParameter("currentYear", 2026) .setParameter("title", "Hairspray") .getResultList(); for (var row : arithmeticResult) { System.out.println("Title: " + row[0] + ", Age: " + row[1]); }
La extensión Hibernate ORM traduce la expresión calculada anterior a la siguiente etapa $project:
{ "$project": { "title": true, "age": { "$subtract": [ 2026, "$year" ] }, "_id": 0 } }
Filtrar en una expresión calculada
En la cláusula WHERE, puede comparar una expresión calculada con un valor o comparar dos valores de campo entre sí. Cuando ninguno de los lados de la comparación es una referencia directa a un campo o valor, la extensión Hibernate ORM envuelve la comparación en el operador $expr de MongoDB. Las comparaciones entre un campo y un valor siguen utilizando la forma compacta { field: { operator: value } }.
El siguiente ejemplo recupera "Hairspray" películas estrenadas menos de 20 años antes de 2026:
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()); }
var computedFilterResult = entityManager.createQuery( "select m from Movie m where m.title = :title and :currentYear - m.year < 20", Movie.class) .setParameter("title", "Hairspray") .setParameter("currentYear", 2026) .getResultList(); for (var m : computedFilterResult) { System.out.println("Title: " + m.getTitle() + ", Year: " + m.getYear()); }
La extensión Hibernate ORM traduce la consulta anterior a la siguiente etapa $match, en la que la comparación title utiliza la forma compacta y la comparación calculada utiliza $expr:
{ "$match": { "$and": [ { "title": { "$eq": "Hairspray" } }, { "$expr": { "$lt": [ { "$subtract": [ 2026, "$year" ] }, 20 ] } } ] } }
Proyectar un resultado de comparación
Puedes usar una comparación en una instrucción SELECT para devolver su resultado booleano en lugar de usar la comparación como un filtro.
El siguiente ejemplo devuelve el título de cada película "Hairspray" y si la película se estrenó después de 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]); }
var comparisonResult = entityManager.createQuery( "select m.title, m.year > 2000 as isRecent from Movie m where m.title = :title", Object[].class) .setParameter("title", "Hairspray") .getResultList(); for (var row : comparisonResult) { System.out.println("Title: " + row[0] + ", Recent: " + row[1]); }
La extensión Hibernate ORM traduce la comparación anterior a la siguiente etapa $project:
{ "$project": { "title": true, "isRecent": { "$gt": [ "$year", 2000 ] }, "_id": 0 } }
Expresiones de casos de uso para lógica condicional
Una expresión CASE devuelve un valor diferente para cada condición que especifique. La extensión Hibernate ORM admite expresiones CASE simples y con búsqueda tanto de HQL como de JPQL:
Caso simple: La expresión que sigue a la palabra clave
CASEse compara para comprobar si es igual al valor de cada cláusulaWHEN. Un ejemplo de una expresión de caso simple escase year when 2000 then 'Modern' else 'Classic' end.Caso de búsqueda: Cada cláusula
WHENespecifica un predicado. Un ejemplo de una expresión de caso de búsqueda escase when year > 2000 then 'Modern' else 'Classic' end.
La extensión Hibernate ORM traduce una expresión CASE al operador $switch de MongoDB, que crea una rama para cada cláusula WHEN y evalúa las ramas en el orden en que se especifican. La cláusula ELSE se convierte en el valor default de $switch. Si se omite la cláusula ELSE, la expresión devuelve null cuando ninguna rama coincide.
Una expresión CASE puede devolver una expresión calculada, y puede utilizar una expresión CASE en las siguientes posiciones:
Una cláusula
SELECT, como se muestra en el siguiente ejemplo.Un operando de una comparación en una cláusula
WHERE, que la extensión ORM de Hibernate envuelve en el operador$exprde MongoDB.La cláusula
SETde una instrucción de actualización masiva. Para ver un ejemplo, consulte la sección "Ejemplo de actualización múltiple basada en lógica condicional" en la guía "Realizar operaciones CRUD".
El siguiente ejemplo devuelve el título de cada película "Hairspray" y una etiqueta que depende del valor year de la película:
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]); }
var caseResult = entityManager.createQuery( "select m.title, case when m.year > 2000 then 'Modern' else 'Classic' end as era " + "from Movie m where m.title = :title", Object[].class) .setParameter("title", "Hairspray") .getResultList(); for (var row : caseResult) { System.out.println("Title: " + row[0] + ", Era: " + row[1]); }
La extensión Hibernate ORM traduce la expresión CASE anterior a la siguiente etapa $project:
{ "$project": { "title": true, "era": { "$switch": { "branches": [ { "case": { "$gt": [ "$year", 2000 ] }, "then": "Modern" } ], "default": "Classic" } }, "_id": 0 } }
Importante
Limitaciones de la expresión CASE
Debido a que una expresión CASE produce una expresión de agregación de MongoDB, no se puede usar en una posición que requiera una referencia de campo o un valor literal. La extensión Hibernate ORM genera una excepción FeatureNotSupportedException si se usa una expresión CASE:
en una cláusula
ORDER BY, a menos que la misma expresiónCASEsea una claveGROUP BY.como la expresión de coincidencia de un predicado
LIKE.como expresión de prueba de un predicado
INoIS NULL.como predicado de una cláusula
WHEREen lugar de un operando de una.
Utilice operadores de predicado
La extensión Hibernate ORM admite los siguientes operadores de comparación de predicados en sus sentencias de consulta:
Nota
La extensión Hibernate ORM no admite todos los operadores de comparación. Para obtener más información sobre las limitaciones de compatibilidad, consulte la sección "Compatibilidad con consultas" en la página "Compatibilidad de funciones".
EXISTS
El predicado EXISTS coincide con los documentos que tienen un campo específico y devuelve solo un resultado para cada documento padre coincidente, independientemente de cuántos elementos de la matriz coincidan.
Nota
Limitaciones de subconsultas EXISTS
La extensión Hibernate ORM admite subconsultas EXISTS únicamente sobre un campo de matriz de la entidad principal, y únicamente en la cláusula WHERE. La extensión Hibernate ORM no admite subconsultas EXISTS que:
Consultar una entidad sin especificar primero un campo.
Comparar campos en el mismo documento principal.
Aparece en la cláusula
SELECT
Para ver un ejemplo completo, consulte la sección "Consulta sobre elementos de una matriz incrustada" de esta guía.
ENTRE
El predicado BETWEEN coincide con los documentos que tienen un valor de campo dentro de un rango especificado.
El siguiente ejemplo utiliza el predicado BETWEEN para recuperar documentos que tienen un valor year entre 2012 y 2013, ambos inclusive, de la colección sample_mflix.movies:
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()); }
var betweenResult = entityManager.createQuery("select m from Movie m where m.year between :start and :end", Movie.class) .setParameter("start", 2012) .setParameter("end", 2013) .getResultList(); for (var m : betweenResult) { System.out.println("Title: " + m.getTitle()); }
La extensión Hibernate ORM traduce el predicado BETWEEN anterior a la siguiente etapa $match:
{ "$match": { "year": { "$gte": 2012, "$lte": 2013 } } }
in
El predicado IN coincide con los documentos donde el valor de un campo es igual a cualquier valor de una lista específica. Puede proporcionar los valores de la lista como literales, parámetros con nombre o parámetros posicionales.
El siguiente ejemplo utiliza el predicado IN para recuperar documentos que tienen un valor year igual a 1994 o 1996 de la colección sample_mflix.movies:
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()); }
var inResult = entityManager.createQuery("select m from Movie m where m.year in (:first, :second)", Movie.class) .setParameter("first", 1994) .setParameter("second", 1996) .getResultList(); for (var m : inResult) { System.out.println("Title: " + m.getTitle()); }
La extensión Hibernate ORM traduce el predicado IN anterior a la siguiente etapa $match:
{ "$match": { "year": { "$in": [ 1994, 1996 ] } } }
Una lista vacía es válida, pero nunca coincide con ningún documento. Por ejemplo, year in () no coincide con ningún documento.
Nota
Limitaciones del predicado IN
La extensión Hibernate ORM admite el predicado IN solo cuando el valor a la izquierda de IN es una ruta de campo. La extensión Hibernate ORM no admite los predicados IN que:
Toma una subconsulta como la lista de valores.
Comprueba un valor comparándolo con una expresión de matriz, como en
:value in m.cast. Para comparar un valor con un campo de matriz, utiliza la funciónarray_contains().
Para obtener más información sobre cómo consultar una matriz, consulte la sección "Consultar un campo de matriz" de esta guía.
NO EN
El predicado NOT IN coincide con documentos en los que el valor de un campo no coincide con ningún valor de una lista específica. NOT IN acepta los mismos formatos de lista y tiene las mismas limitaciones que el predicado IN.
El siguiente ejemplo utiliza el predicado NOT IN para recuperar documentos que tienen un valor title distinto de "Romeo and Juliet" o "Best in Show" de la colección sample_mflix.movies. Dado que NOT IN excluye solo los valores enumerados, el ejemplo llama al método setMaxResults() para limitar el conjunto de resultados a diez documentos:
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()); }
var notInResult = entityManager.createQuery("select m from Movie m where m.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()); }
La extensión Hibernate ORM traduce el predicado NOT IN anterior a la siguiente etapa $match:
{ "$match": { "title": { "$nin": [ "Romeo and Juliet", "Best in Show" ] } } }
Debido a que $nin compara cada documento con una lista vacía de valores, title not in () compara todos los documentos.
Nota
NO EN Limitaciones
La extensión Hibernate ORM admite el predicado NOT IN solo cuando el valor a la izquierda de NOT IN es una ruta de campo. La extensión Hibernate ORM no admite los predicados NOT IN que:
Toma una subconsulta como la lista de valores.
Comprueba un valor comparándolo con una expresión que contiene valores de matriz, como en
:value not in m.cast.
Nota
Semántica nula
Los predicados de valor de fila siguen la semántica de valores nulos del lenguaje de consulta de MongoDB en lugar de la lógica ternaria del ORM de Hibernate, por lo que un predicado NOT IN coincide con documentos en los que un componente es nulo o falta. Para obtener más información, consulte la sección «Comparar valores de campo con valores nulos» de esta guía.
ES NULO
El predicado IS NULL coincide con los documentos que tienen un campo específico con un valor nulo o faltante.
Para comparar un campo con null utilizando un operador de comparación en lugar de un predicado, consulte la sección Comparar valores de campo con Null de esta guía.
El siguiente ejemplo utiliza el predicado IS NULL para recuperar documentos que tienen un valor faltante o null cast de la colección sample_mflix.movies:
var isNullResult = session.createQuery("from Movie where cast is null", Movie.class) .getResultList(); for (var m : isNullResult) { System.out.println("Title: " + m.getTitle()); }
var isNullResult = entityManager.createQuery("select m from Movie m where m.cast is null", Movie.class) .getResultList(); for (var m : isNullResult) { System.out.println("Title: " + m.getTitle()); }
La extensión Hibernate ORM traduce el predicado IS NULL precedente a la siguiente etapa $match, que coincide con los documentos donde el campo es explícitamente null o falta:
{ "$match": { "cast": { "$eq": null } } }
NO ES NULO
El predicado IS NOT NULL coincide con los documentos que tienen un campo con un valor no nulo o no faltante.
El siguiente ejemplo utiliza el predicado IS NOT NULL para recuperar documentos que tienen un valor directors de la colección sample_mflix.movies:
var isNotNullResult = session.createQuery("from Movie where directors is not null", Movie.class) .getResultList(); for (var m : isNotNullResult) { System.out.println("Title: " + m.getTitle()); }
var isNotNullResultEm = entityManager.createQuery("select m from Movie m where m.directors is not null", Movie.class) .getResultList(); for (var m : isNotNullResultEm) { System.out.println("Title: " + m.getTitle()); }
La extensión Hibernate ORM traduce el predicado IS NOT NULL precedente a la siguiente etapa $match, que coincide con los documentos donde el campo existe y no es explícitamente null:
{ "$match": { "directors": { "$ne": null } } }
COMO
El predicado LIKE distingue entre mayúsculas y minúsculas y coincide con documentos donde el valor de un campo coincide con un patrón especificado. El patrón se compara con el valor completo del campo y puede utilizar los siguientes caracteres comodín:
%: Coincide con cero o más caracteres._: Coincide exactamente con un carácter.
Para que coincida con un prefijo, incluya % al final del patrón, y para que coincida con un sufijo, incluya % al principio del patrón.
Tip
Personajes comodín de escape
Si desea que coincida con % o _ como carácter literal, utilice la cláusula ESCAPE. Por ejemplo, title like '100!%' escape '!' coincide con el valor "100%". Puede usar ESCAPE con %, _ o el propio carácter de escape. Si lo usa con cualquier otro carácter o lo deja al final del patrón, la extensión Hibernate ORM generará una excepción IllegalArgumentException.
El siguiente ejemplo utiliza el predicado LIKE para recuperar documentos que tienen un valor title que comienza con "W", seguido de cualquier carácter individual y luego "r", de la colección 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()); }
var likeResultEm = entityManager.createQuery("select m from Movie m where m.title like 'W_r%'", Movie.class) .getResultList(); for (var m : likeResultEm) { System.out.println("Title: " + m.getTitle()); }
La extensión Hibernate ORM traduce el predicado LIKE anterior a la siguiente etapa $match:
{ "$match": { "title": { "$regex": /^W.r.*$/s } } }
Nota
Limitaciones del predicado LIKE
El valor que compare con LIKE debe ser una cadena literal, como '%War%'. La extensión Hibernate ORM no admite un parámetro vinculado (like :pattern), otro campo (like m.plot) o un valor calculado (like concat('War', '%')) para el patrón, y lanza un FeatureNotSupportedException si usa uno.
Para obtener más información sobre el predicado HQL LIKE, consulte la Guía del lenguaje de consulta de Hibernate en la documentación de Hibernate ORM.
NO ES COMO
El predicado NOT LIKE coincide con los documentos en los que el valor de un campo no coincide con el patrón especificado. La extensión Hibernate ORM niega el filtro $regex que produce el predicado LIKE y utiliza el mismo comportamiento de coincidencia de patrones y las mismas restricciones que el predicado LIKE.
El siguiente ejemplo utiliza el predicado NOT LIKE para recuperar documentos que tienen un valor title que no comienza con "The" de la colección sample_mflix.movies. Dado que el predicado coincide con la mayoría de los documentos, el ejemplo llama al método setMaxResults() para limitar el conjunto de resultados a cinco documentos:
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()); }
var notLikeResultEm = entityManager.createQuery("select m from Movie m where m.title not like 'The%'", Movie.class) .setMaxResults(5) .getResultList(); for (var m : notLikeResultEm) { System.out.println("Title: " + m.getTitle()); }
La extensión Hibernate ORM traduce el predicado NOT LIKE anterior a la siguiente etapa $match:
{ "$match": { "$nor": [ { "title": { "$regex": /^The.*$/s } } ] } }
ILIKE
El predicado ILIKE es la forma insensible a mayúsculas y minúsculas del predicado LIKE. La extensión Hibernate ORM marca el filtro $regex que produce el predicado LIKE como insensible a mayúsculas y minúsculas y utiliza el mismo comportamiento de coincidencia de patrones y las mismas restricciones que el predicado LIKE.
El siguiente ejemplo utiliza el predicado ILIKE para recuperar documentos que tienen un valor title que contiene "Star" de la colección 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()); }
var ilikeResultEm = entityManager.createQuery("select m from Movie m where m.title ilike '%Star%'", Movie.class) .getResultList(); for (var m : ilikeResultEm) { System.out.println("Title: " + m.getTitle()); }
La extensión Hibernate ORM traduce el predicado ILIKE anterior a la siguiente etapa $match:
{ "$match": { "title": { "$regex": /^.*Star.*$/is } } }
NO ME GUSTA
El predicado NOT ILIKE es la forma insensible a mayúsculas y minúsculas del predicado NOT LIKE. La extensión ORM de Hibernate niega el filtro $regex insensible a mayúsculas y minúsculas que produce el predicado ILIKE y utiliza el mismo comportamiento de coincidencia de patrones y las mismas restricciones que el predicado LIKE.
El siguiente ejemplo utiliza el predicado NOT ILIKE para recuperar documentos que tienen un valor title que no contiene "The" de la colección sample_mflix.movies. Dado que el predicado coincide con la mayoría de los documentos, el ejemplo llama al método setMaxResults() para limitar el conjunto de resultados a cinco documentos:
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()); }
var notIlikeResultEm = entityManager.createQuery("select m from Movie m where m.title not ilike '%The%'", Movie.class) .setMaxResults(5) .getResultList(); for (var m : notIlikeResultEm) { System.out.println("Title: " + m.getTitle()); }
La extensión Hibernate ORM traduce el predicado NOT ILIKE anterior a la siguiente etapa $match:
{ "$match": { "$nor": [ { "title": { "$regex": /^.*The.*$/is } } ] } }
Utilizar filtros lógicos
Puede usar los siguientes operadores en sus sentencias de consulta para combinar múltiples criterios de consulta:
and: Coincidencia con todos los criteriosorCoincide con cualquier criterionot: No cumple con los criterios
El siguiente ejemplo recupera un documento que tiene un valor de title de "The Godfather" y un valor de year de 1972 de la colección sample_mflix.movies:
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());
var logicalResult = entityManager.createQuery("select m from Movie m where m.title = :t and m.year = :y", Movie.class) .setParameter("t", "The Godfather") .setParameter("y", 1972) .getSingleResult(); System.out.println("Title: " + logicalResult.getTitle());
Consultar un campo de llave primaria
Para recuperar un documento en función de su valor ObjectId, puedes pasar ese valor como argumento al método get(), si estás usando una sesión, o al método find(), si usas un gestor de entidades.
El siguiente ejemplo recupera un documento de la colección sample_mflix.movies por su valor ObjectId:
var movieById = session.get(Movie.class, new ObjectId("573a13a8f29313caabd1d53c"));
var movieById = entityManager.find(Movie.class, new ObjectId("573a13a8f29313caabd1d53c"));
Consultar un documento incrustado
Puedes representar documentos incrustados de MongoDB creando elementos incrustables agregados @Struct. Luego, puedes usar la extensión Hibernate ORM para obtener elementos incrustables agregados @Struct asociados con entidades principales específicas.
Tip
Para obtener más información sobre cómo representar documentos incrustados, consulta Datos integrados en la guía Crear entidades.
El siguiente ejemplo recupera documentos que tienen un valor de title de "Hairspray" de la colección sample_mflix.movies. Luego, el código recupera el campo awards, que almacena Awards agregado @Struct integrable, e imprime el campo wins del tipo integrable Awards:
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()); }
var embeddedResult = entityManager.createQuery("select m.awards from Movie m where m.title = :title", Awards.class) .setParameter("title", "Hairspray") .getResultList(); for (var a : embeddedResult) { System.out.println("Award wins: " + a.getWins()); }
Consultar un campo en un documento incrustado.
Puedes hacer referencia a un campo de un tipo incrustable usando una expresión de ruta con puntos en las cláusulas SELECT, WHERE, ORDER BY y UPDATE de una consulta HQL o JPQL. También puedes encadenar varios nombres de incrustables en una expresión de ruta para hacer referencia a un campo de un incrustable anidado dentro de otro incrustable.
Importante
Limitaciones de query
Las expresiones de ruta no admiten campos incrustables que utilicen la anotación @ColumnTransformer para definir una expresión de lectura personalizada.
La extensión Hibernate ORM también rechaza las siguientes asignaciones incrustables agregadas @Struct cuando construye el modelo de entidad:
Un elemento incrustable agregado
@Structutilizado como un campo@IdUna jerarquía incrustable agregada polimórfica
@Struct
No se puede utilizar una expresión de ruta para hacer referencia a un campo en estos tipos.
El siguiente ejemplo utiliza una expresión de ruta para filtrar documentos en la colección sample_mflix.movies. Hay dos películas "Hairspray" en la colección sample_mflix.movies. Una película "Hairspray" es de 1998 y la otra es de 2007. La consulta coincide con los documentos que tienen un valor title igual a "Hairspray" y un valor awards.wins mayor que 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()); }
var matchingDocument = entityManager.createQuery("select m from Movie m where m.title = :title and m.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()); }
Consulta sobre elementos de una matriz incrustada
Cuando un campo de su entidad almacena una matriz de elementos incrustables agregados @Struct, puede usar una subconsulta EXISTS para encontrar documentos principales en los que al menos un elemento de esa matriz cumpla con sus criterios. La extensión Hibernate ORM traduce la subconsulta al operador $elemMatch de MongoDB, que aplica todos los criterios al mismo elemento de la matriz.
Datos de muestra
Nota
Utilice la base de datos sample_restaurants para esta sección.
Los ejemplos de esta sección utilizan la colección sample_restaurants.restaurants en lugar de la colección sample_mflix.movies que se utiliza en otras partes de esta guía.
Para ejecutar estos ejemplos, conéctese a la base de datos sample_restaurants en su cadena de conexión. Para obtener más información sobre la base de datos sample_restaurants, consulte los conjuntos de datos de ejemplo de Atlas.
La siguiente entidad Restaurant se asigna a la colección restaurants y almacena una lista de elementos incrustables Grade en su campo 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; public class Restaurant { 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; } }
El siguiente elemento incrustable agregado Grade @Struct representa cada elemento del array grades:
package org.example; import jakarta.persistence.*; import org.hibernate.annotations.Struct; 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
Para obtener más información sobre las matrices de elementos incrustables, consulte Datos incrustados en la guía Crear entidades.
Los documentos de la colección restaurants se parecen a los siguientes:
{ "_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 } ] }
Ejemplo
El siguiente ejemplo recupera restaurantes que tienen al menos un elemento de la matriz grades con un valor grade igual a "B" y un valor score igual a 12. Dado que ambos criterios aparecen en la misma subconsulta, deben coincidir con el mismo elemento de la matriz:
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()); }
var existsResultEm = entityManager.createQuery( "select r 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 : existsResultEm) { System.out.println("Name: " + r.getName()); }
La extensión Hibernate ORM traduce la subconsulta EXISTS anterior a la siguiente etapa $match:
{ "$match": { "grades": { "$elemMatch": { "grade": { "$eq": "B" }, "score": { "$eq": 12 } } } } }
Query un campo de arreglo
La extensión Hibernate ORM admite las siguientes funciones para consultar campos de arreglo:
array_contains(): Coincide documentos donde un campo de arreglo contiene un valor especificadoarray_contains_nullable(): Coincidir con documentos donde un campo de arreglo contiene un valor especificado, incluyendo valoresnullarray_includes(): Coincide con documentos donde un campo de arreglo incluye otro valor de arregloarray_includes_nullable()Coincidir con documentos donde un campo de arreglo incluya otro valor de arreglo, incluidos valoresnull
Tip
Para aprender más sobre las funciones de arrays, consulte Funciones para el manejo de arrays en la guía de usuario de Hibernate ORM.
El siguiente ejemplo utiliza la función array_contains() para recuperar documentos que tienen el valor "Kathryn Hahn" en el campo de arreglo cast de la colección sample_mflix.movies:
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()); }
var arrayResult = entityManager.createQuery("select m from Movie m where array_contains(m.cast, :actor)", Movie.class) .setParameter("actor", "Kathryn Hahn") .getResultList(); for (var m : arrayResult) { System.out.println("Title: " + m.getTitle()); }
Utilice funciones de agregación
En las consultas HQL y JPQL, puede utilizar funciones de agregación para agrupar y resumir los resultados de la consulta, o para filtrar los resultados agrupados mediante una cláusula HAVING. HQL y JPQL admiten las siguientes funciones de agregación:
count()sum()avg()min()max()
Nota
Requisitos de AGRUPAR POR
Las funciones de agregación requieren una cláusula GROUP BY. Las consultas que utilizan una función de agregación sin agrupar los resultados, como select count(*) from Movie, aún no son compatibles. Los campos que no son de agregación en la cláusula SELECT también deben aparecer en la cláusula GROUP BY.
El siguiente ejemplo agrupa las películas estrenadas entre 1920 y 1924 por año. Para cada año, devuelve el número de películas y la duración total de todas ellas. La cláusula HAVING incluye solo los años cuyas películas tienen una duración total superior a 300 minutos y ordena los resultados por año.
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]); }
var aggregateResult = entityManager.createQuery( "select m.year, count(m), sum(m.runtime) from Movie m where m.year between 1920 and 1924 " + "group by m.year having sum(m.runtime) > 300 order by m.year", Object[].class) .getResultList(); for (var row : aggregateResult) { System.out.println("Year: " + row[0] + ", Count: " + row[1] + ", Total runtime: " + row[2]); }
Información Adicional
Para obtener más información sobre cómo realizar otras operaciones en tus datos de MongoDB, consulta la guía Realizar Operaciones CRUD.
Para aprender a realizar consultas entre entidades vinculadas por una asociación, consulte la guía "Unir entidades entre colecciones".
Para aprender cómo devolver parte de un valor de fecha y hora o cómo representar un valor de fecha y hora como una cadena, consulte la guía "Uso de funciones de fecha y hora en consultas".
Para aprender más sobre el uso de HQL y JPQL para ejecutar queries, consulte Una guía sobre el languaje del query de Hibernate en la documentación de Hibernate ORM.