Definición
Modificado en la versión 5.0.
$exprPermite el uso de expresiones de agregación dentro del lenguaje de consulta.
Compatibilidad
Puedes usar $expr para implementaciones alojadas en los siguientes entornos:
MongoDB Atlas: El servicio totalmente gestionado para implementaciones de MongoDB en la nube
MongoDB Enterprise: La versión basada en suscripción y autogestionada de MongoDB
MongoDB Community: La versión de MongoDB con código fuente disponible, de uso gratuito y autogestionada.
Sintaxis
$expr tiene la siguiente sintaxis:
{ $expr: { <expression> } }
Los argumentos pueden ser cualquier expresión de agregación válida. Para más información, consulte Expresiones.
Comportamiento
$expr puede compilar expresiones de query que comparen campos del mismo documento en una $match etapa.
Si la etapa$matchforma parte de una etapa$lookup, $exprpuede comparar campos usando variables let. Consulte "Realizar múltiples uniones y una subconsulta correlacionada con $lookup" para ver un ejemplo.
Los operadores de comparación $eq, $lt, $lte, $gt y $gte colocados en un operador $expr pueden utilizar un índice en la colección from referenciada en una etapa $lookup. Limitaciones:
Los índices solo pueden utilizarse para comparaciones entre campos y constantes, por lo que el operando
letdebe resolverse en una constante.Por ejemplo, una comparación entre
$ay un valor constante puede utilizar un índice, pero una comparación entre$ay$bno puede.Los índices no se utilizan para comparaciones donde el operando
letse resuelve en un valor vacío o faltante.Los índices multiclave no se utilizan.
Ejemplos
Comparar dos campos de un único documento
Considera una colección monthlyBudget con los siguientes documentos:
db.monthlyBudget.insertMany( [ { _id : 1, category : "food", budget : 400, spent : 450 }, { _id : 2, category : "drinks", budget : 100, spent : 150 }, { _id : 3, category : "clothes", budget : 100, spent : 50 }, { _id : 4, category : "misc", budget : 500, spent : 300 }, { _id : 5, category : "travel", budget : 200, spent : 650 } ] )
La siguiente operación utiliza $expr para encontrar documentos donde el monto de spent excede el budget:
db.monthlyBudget.find( { $expr: { $gt: [ $spent , $budget ] } } )
La operación devuelve los siguientes resultados:
{ _id : 1, category : "food", budget : 400, spent : 450 } { _id : 2, category : "drinks", budget : 100, spent : 150 } { _id : 5, category : "travel", budget : 200, spent : 650 }
Uso de $expr con declaraciones condicionales
Algunas consultas requieren la capacidad de ejecutar lógica condicional al definir un filtro de consulta. La canalización de agregación proporciona el operador$condpara expresar sentencias condicionales. Al usar$exprcon el operador$cond, puede especificar un filtro condicional para su sentencia de consulta.
Crea una colección de ejemplo supplies con los siguientes documentos:
db.supplies.insertMany( [ { _id : 1, item : "binder", qty : Int32("100"), price : Decimal128("12") }, { _id : 2, item : "notebook", qty : Int32("200"), price : Decimal128("8") }, { _id : 3, item : "pencil", qty : Int32("50"), price : Decimal128("6") }, { _id : 4, item : "eraser", qty : Int32("150"), price : Decimal128("3") }, { _id : 5, item : "legal pad", qty : Int32("42"), price : Decimal128("10") } ] )
Supongamos que para una próxima venta el mes siguiente, quieres descontar los precios de tal forma que:
Si
qtyes mayor o igual a 100, el precio con descuento será el 50% delprice.Si
qtyes menor que 100, el precio con descuento es el 75% deprice.
Antes de aplicar los descuentos, se necesita saber qué artículos de la colección supplies tienen un precio con descuento inferior a 5.
El siguiente ejemplo utiliza $expr con para calcular el precio con descuento $cond según qty y $lt para devolver documentos cuyo precio de descuento calculado sea menor Decimal128("5") que:
// Aggregation expression to calculate discounted price let discountedPrice = { $cond: { if: { $gte: ["$qty", 100] }, then: { $multiply: ["$price", Decimal128("0.50")] }, else: { $multiply: ["$price", Decimal128("0.75")] } } }; // Query the supplies collection using the aggregation expression db.supplies.find( { $expr: { $lt:[ discountedPrice, Decimal128("5") ] } });
La siguiente tabla muestra el precio con descuento de cada documento y si el precio con descuento es inferior a Decimal128("5") (es decir, si el documento cumple la condición de la query).
Documento | Precio con descuento | < Decimal128("5") |
|---|---|---|
{"_id": 1, "item": "binder", "qty": 100, "price": Decimal128("12") } | Decimal128("6.00") |
|
{"_id": 2, "item": "notebook", "qty": 200, "price": Decimal128("8") } | Decimal128("4.00") |
|
{"_id": 3, "item": "pencil", "qty": 50, "price": Decimal128("6") } | Decimal128("4.50") |
|
{"_id": 4, "item": "eraser", "qty": 150, "price": Decimal128("3") } | Decimal128("1.50") |
|
{"_id": 5, "item": "legal pad", "qty": 42, "price": Decimal128("10") } | Decimal128("7.50") |
|
La db.collection.find() operación devuelve los documentos cuyo precio de descuento calculado es menor que Decimal128("5"):
{ _id : 2, item : "notebook", qty : 200 , price : Decimal128("8") } { _id : 3, item : "pencil", qty : 50 , price : Decimal128("6") } { _id : 4, item : "eraser", qty : 150 , price : Decimal128("3") }
Aunque $cond calcula un precio con descuento en efectivo, ese precio no se refleja en los documentos que se devuelven. En su lugar, los documentos que se devuelven representan los documentos que coinciden en su estado original. La operación de búsqueda no devolvió los documentos binder o legal pad, ya que su precio con descuento era mayor que 5.