En MongoDB, puede usar el $subtract
operador de tubería de agregación para restar números y/o fechas.
Específicamente, $subtract
puede hacer las siguientes tres cosas:
- Restar dos números para obtener la diferencia
- Reste un número (en milisegundos) de una fecha y devuelva la fecha resultante
- Reste dos fechas para obtener la diferencia en milisegundos
El $subtract
El operador acepta los valores como argumentos. Los argumentos pueden ser cualquier expresión válida siempre que se resuelvan en números y/o fechas. Para restar un número de una fecha, la fecha debe ser el primer argumento..
Datos de muestra
Supongamos que tenemos una colección llamada data
con el siguiente documento:
{ "_id" : 1, "a" : 20000, "b" : 250, "start" : ISODate("2021-01-03T00:00:00Z"), "end" : ISODate("2021-01-03T23:30:15.100Z") }
Restar números
Podemos usar el $subtract
operador para restar el a
campo del b
campo (o viceversa).
Ejemplo:
db.data.aggregate(
[
{ $project: {
_id: 0,
a: 1,
b: 1,
result: {
$subtract: [ "$a", "$b" ] } }
}
]
)
Resultado:
{ "a" : 20000, "b" : 250, "result" : 19750 }
Restar un número de una fecha
Si el primer argumento es una fecha y el segundo argumento es un número, el $subtract
el operador resta el número de la fecha en milisegundos.
Ejemplo:
db.data.aggregate(
[
{ $project: {
_id: 0,
b: 1,
start: 1,
result: {
$subtract: [ "$start", "$b" ] } }
}
]
).pretty()
Resultado:
{ "b" : 250, "start" : ISODate("2021-01-03T00:00:00Z"), "result" : ISODate("2021-01-02T23:59:59.750Z") }
Podemos ver que se han restado 250 milisegundos a la fecha.
Cuando restamos un número de una fecha, la fecha debe ser el primer argumento con el número como segundo argumento.
Esto es lo que sucede si cambiamos los argumentos:
db.data.aggregate(
[
{ $project: {
_id: 0,
b: 1,
start: 1,
result: {
$subtract: [ "$b", "$start" ] } }
}
]
).pretty()
Resultado:
uncaught exception: Error: command failed: { "ok" : 0, "errmsg" : "cant $subtract adate from a double", "code" : 16556, "codeName" : "Location16556" } : aggregate failed : [email protected]/mongo/shell/utils.js:25:13 [email protected]/mongo/shell/assert.js:18:14 [email protected]/mongo/shell/assert.js:618:17 [email protected]/mongo/shell/assert.js:708:16 [email protected]/mongo/shell/db.js:266:5 [email protected]/mongo/shell/collection.js:1046:12 @(shell):1:1
Recibimos un error que nos dice que no se puede restar una fecha de un doble.
Devolver la diferencia entre dos fechas
Si ambos argumentos son fechas, entonces $subtract
operador devuelve la diferencia entre las dos fechas en milisegundos.
Ejemplo:
db.data.aggregate(
[
{ $project: {
_id: 0,
start: 1,
end: 1,
result: {
$subtract: [ "$end", "$start" ] } }
}
]
).pretty()
Resultado:
{ "start" : ISODate("2021-01-03T00:00:00Z"), "end" : ISODate("2021-01-03T23:30:15.100Z"), "result" : NumberLong(84615100) }
Si cambiamos las fechas, el resultado se convierte en un valor negativo:
db.data.aggregate(
[
{ $project: {
_id: 0,
start: 1,
end: 1,
result: {
$subtract: [ "$start", "$end" ] } }
}
]
).pretty()
Resultado:
{ "start" : ISODate("2021-01-03T00:00:00Z"), "end" : ISODate("2021-01-03T23:30:15.100Z"), "result" : NumberLong(-84615100) }
Pasar el número incorrecto de argumentos
El $subtract
El operador acepta exactamente dos argumentos. Pasar el número incorrecto de argumentos da como resultado un error.
Ejemplo:
db.data.aggregate(
[
{ $project: {
result: {
$subtract: [ "$a" ] } }
}
]
)
Resultado:
uncaught exception: Error: command failed: { "ok" : 0, "errmsg" : "Invalid $project :: caused by :: Expression $subtract takes exactly 2 arguments. 1 were passed in.", "code" : 16020, "codeName" : "Location16020" } : aggregate failed : [email protected]/mongo/shell/utils.js:25:13 [email protected]/mongo/shell/assert.js:18:14 [email protected]/mongo/shell/assert.js:618:17 [email protected]/mongo/shell/assert.js:708:16 [email protected]/mongo/shell/db.js:266:5 [email protected]/mongo/shell/collection.js:1046:12 @(shell):1:1
Pasar valores nulos
Pasando dos null
los valores dan como resultado null
siendo devuelto.
Ejemplo:
db.data.aggregate(
[
{ $project: {
result: {
$subtract: [ null, null ] } }
}
]
)
Resultado:
{ "_id" : 1, "result" : null }