If I have documents in the following schema saved in my mongoDB:
{
createdDate: Date,
lastUpdate: Date
}
is it possible to query for documents where the period of time between creation and the last update is e.g. greater than one day?
Use operator gteandlt to find objects between two dates in MongoDB.
The MongoDB timestamp looks similar to Date data type, where it has the same 64-bit value. But it also has a few aspects where it differs from the Date. The MongoDB Timestamp is quite used for the internal purpose, and with every single instance of mongodb, the values generated for timestamp are unique.
We can use date () command to get a date as a string in a query without the new keyword or MongoDB shell.
In MongoDB, you can use the $subtract aggregation pipeline operator to subtract numbers and/or dates. Specifically, $subtract can do the following three things: Subtract two numbers to return the difference. Subtract a number (in milliseconds) from a date and return the resulting date.
Starting in Mongo 5
, it's a perfect use case for the new $dateDiff
aggregation operator:
// { created: ISODate("2021-12-05T13:20"), lastUpdate: ISODate("2021-12-06T05:00") }
// { created: ISODate("2021-12-04T09:20"), lastUpdate: ISODate("2021-12-05T18:00") }
db.collection.aggregate([
{ $match: {
$expr: {
$gt: [
{ $dateDiff: { startDate: "$created", endDate: "$lastUpdate", unit: "hour" } },
24
]
}
}}
])
// { created: ISODate("2021-12-04T09:20"), lastUpdate: ISODate("2021-12-05T18:00") }
This computes the number of hours of difference between the created
and lastUpdate
dates and checks if it's more than 24
hour
s.
Best option is to use the $redact
aggregation pipeline stage:
db.collection.aggregate([
{ "$redact": {
"$cond": {
"if": {
"$gt": [
{ "$subtract": [ "$lastUpdate", "$createdDate" ] },
1000 * 60 * 60 * 24
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
So you are looking at the milliseconds value from the difference being greater than the milliseconds value for one day. The $subtract
does the math for the difference, and when two dates are subtracted the difference in miliseconds is returned.
The $redact
operator takes a logical expression as "if", and where that condition is true
it takes the action in "then" which is to $$KEEP
the document. Where it is false
then the document is removed from results with $$PRUNE
.
Note that since this is a logical condition and not a set value or a range of values, then an "index" is not used.
Since the operations in the aggregation pipeline are natively coded, this is the fastest execution of such a statement that you can get though.
The alternate is JavaScript evaluation with $where
. This takes a JavaScript function expression that needs to similarly return a true
or false
value. In the shell you can shorthand like this:
db.collection.find(function() {
return ( this.lastUpdate.valueOf() - this.createdDate.valueOf() )
> ( 1000 * 60 * 60 * 24 );
})
Same thing, except that JavaScript evalution requires interpretation and will run much slower than the .aggregate()
equivalent. By the same token, this type of expression cannot use an index to optimize performance.
For the best results, store the difference in the document. Then you can simply query directly on that property, and of course you can index it as well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With