How to add minutes in date on a MongoDB query - mongodb

Suppose I have this document:
[
{
uuid: 1234,
start: '2022-08-11T16:00:40+08:00',
end: '2022-08-11T16:20:40+08:00'
}
]
How do I get the documents that has a start value in between current date and current date + 30 minutes
This is my current query but it isn't working:
{
start: {
$gte: new Date(),
$lte: {
$dateAdd: {
startDate: new Date(),
unit: 'minute',
amount: 30
}
}
}
}

$dateAdd is an aggregation expression so in order to use it within the query language it must be wrapped with an $expr, like so:
db.collection.find({
$expr: {
$and: [
{
$gte: [
"$start",
"$$NOW"
]
},
{
$lte: [
"$start",
{
$dateAdd: {
startDate: "$$NOW",
unit: "minute",
amount: 30
}
}
]
}
]
}
})
Mongo Playground

Related

How to get the results from the last x days/months/years in MongoDB

I am trying to get a set of results in MongoDB (version 4.2) using only MongoDB Query Language where a specific date is greater than 30 days before today (that is, I need the data from the last 30 days, starting at 00:00h of the day 30 days ago).
I have tried this, but it does not yield any results:
{
date: {
$gte: {
$dateFromParts: {
year: {
$year: new Date()
},
month: {
$month: new Date()
},
day: {
$add: [
{$dayOfMonth: new Date()},
-30
]
}
}
}
}
}
Obviously, I checked that there were results when I entered the date directly this way (being today the 13th of December of 2022):
{date: {$gte: ISODate('2022-11-13')}}
Thank you for the help!
UPDATE 1:
Thanks to #wernfried-domscheit, I came to this solution, although it is very slow. If there was a solution that does not involve using $expr...
{
$expr: {
$gte: [
"$date",
{
$dateFromParts: {
year: {
$year: new Date()
},
month: {
$month: new Date()
},
day: {
$add: [
{
$dayOfMonth: Date()
},
-30
]
}
}
}
]
}
}
Try this one:
db.collection.find({
$expr: {
$gt: [
"$date",
{
$dateSubtract: {
startDate: { $dateTrunc: { date: ISODate(), unit: "day" } },
unit: "day",
amount: 30
}
}
]
}
})
For older version of MongoDB, use
db.collection.find({
$expr: {
$gt: [
"$date",
{
$subtract: [
{
$dateFromParts: {
year: { $year: ISODate() },
month: { $month: ISODate() },
day: { dayOfMonth: ISODate() }
}
},
1000 * 60 * 60 * 24 * 30
]
}
]
}
})

MongoDB view with dynamic dates

I am trying to create a view for records created/modified in last 24 hours.
Is it possible?
Tried creating view as below
db.createView(
"viewname",
"sourcecollection",
[ { $match: {"modifiedTime":{$gte:new Date(Date.now() - 24*60*60*1000), $lte:new Date()}}}]
)
But it translates to static values
{
modifiedTime: {
$gte: ISODate('2022-10-25T23:20:21.602Z'),
$lte: ISODate('2022-10-26T23:20:21.602Z')
}
}
Did read about $$NOW but could not get it working in create view command.
Please suggest
Try this one:
db.createView(
"viewname",
"sourcecollection",
[
{
$match: {
$expr: {
$and: [
{ $gte: ["$modifiedTime", { $dateSubtract: { startDate: "$$NOW", unit: "day", amount: 1 } }] },
{ $lte: ["$modifiedTime", "$$NOW"] }
]
}
}
}
]
)
Based on above post, got it working in Mongo 4.4 with below command.
Dynamic view for records in last 24 hours.
db.createView(
"viewname",
"source",
[ { $match: {$expr: { $gte: [ "modifiedTime" , { $subtract: [ "$$NOW", 24*60*60*1000 ] } ] }}}]
)

How to get reading of collection for previous day, i.e., yesterday using aggregate in mongodb

I have data of various timestamps and I want to create an aggregate pipeline to get sum of a column having yesterdays date. And I don't want to hardcode current date to get yesterday date.
Please suggest how to do it as I am new to Mongodb
Edit :
collection name - consumption_data
documents -
1. id :101, timestamp : 2022-09-10T22:00:00.000+00:00, consumption: 199
2. id :106, timestamp : 2022-09-10T07:00:00.000+00:00, consumption: 201
3. id :108, timestamp : 2022-09-11T12:00:00.000+00:00, consumption: 77
4. id :109, timestamp : 2022-09-11T08:00:00.000+00:00, consumption: 773
If today is 2022-09-11 the I want consumption of yesterday(2022-09-10) without hardcoding the dates
Try this one:
db.consumption_data.aggregate([
{
$match: {
$expr: {
$gt: ["$timestamp", {
$dateSubtract: {
startDate: "$$NOW",
unit: "day",
amount: 1
}
}]
}
}
},
{ $group: { _id: null, consumption: { $sum: "$consumption" } } }
])
Consider the use of $dateTrunc, (i.e. { $dateTrunc: { date: "$$NOW", unit: "day" } }) otherwise it will go back exactly 24 hours from the current time
db.consumption_data.aggregate([
{
$match: {
$expr: {
$and: [
{
$gte: ["$timestamp",
{
$dateSubtract: {
startDate: { $dateTrunc: { date: "$$NOW", unit: "day" } },
unit: "day",
amount: 1
}
}
]
},
{
$lt: ["$timestamp",
{ $dateTrunc: { date: "$$NOW", unit: "day" } }
]
}
]
}
}
},
{ $group: { _id: null, consumption: { $sum: "$consumption" } } }
])
Here is a working solution:
db.totalConsumption_data.aggregate([
{
'$project': {
'month': {
'$month': '$timestamp'
},
'year': {
'$year': '$timestamp'
},
'day': {
'$dayOfMonth': '$timestamp'
},
'timestamp': 1,
'consumption': 1
}
}, {
'$match': {
'month': new Date().getMonth() +1,
'day': new Date().getDate()-1,
'year': new Date().getFullYear()
}
}, {
'$group': {
'_id': null,
'total': {
'$sum': '$consumption'
}
}
}
]

How can I count documents by specific date range

I have switched sql to mongodb recently and I ran into an issue.
Search schema:
new mongoose.Schema({
content: {
type: String,
required: true
},
created_at: {
type: Date,
default: Date.now
})
Some docs:
_id:5e077923f08564374cea9f55
content:"ds"
created_at:2019-12-28T15:47:47.318+00:00
_id:5e077924f08564374cea9f56
content:"ds"
created_at:2019-12-28T15:47:48.545+00:00
_id:5e07792bf08564374cea9f57
content:"d"
created_at:2019-12-28T15:47:55.585+00:00
How can I count search IN A DAY / WEEK / MONTH.
I have an idea, try to convert date to int. But I don't know how to do it.
Thank you very much.
You can use $year, $month to group your date field by year, month and then calculate count for this group. One sample query would look like this -
db.col.aggregate([
{
$group: {
"_id": {
"year" : {
$year : "$createdDate"
},
"month" : {
$month : "$createdDate"
}
},
"count": {
$sum: 1
}
}
}
])
How can I count documents by specific date range
You can specify a range of dates, start and end (and this range can include any number of days: one day, 7 days, 30 days, etc.) and get a count for that.
var start = ISODate("2019-12-25T09:00:00.000+00:00")
var end = ISODate("2019-12-30T17:00:00.000+00:00")
db.dates.aggregate( [
{
$match: {
$and: [ { created_at: { $gte: start } },
{ created_at: { $lte: end } }
]
}
},
{
$group: {
_id: null,
count: { $sum: 1 }
}
}
] )
The query can also be written as a single $group stage:
{
$group: {
_id: null,
count: {
$sum: {
$cond: [
{ $and: [
{ $gte: [ "$created_at", start ] },
{ $lte: [ "$created_at", end ] }
] },
1,
0
]
}
}
}
}

Get Mongodb Documents for a given time range in a date range

I want to find out documents which exist between a certain time period for a given date range.
I have only a field "date" which is stored as a Date object.
For Example -
Find all documents with time between 10:00 am to 23:30 pm for dates ranging from 10th Jan 2018 to 30th Jan 2018
( Also I am currently using Version 3.4)
You can add temporary field which will represent minutes part of your date as 60*$hour + $minute, so it will be 600 for 10 am for instance and then apply your filtering conditions:
db.col.aggregate([
{
$addFields: {
minutes: {
$add: [ { $minute: "$date" }, { $multiply: [ { $hour: "$date" }, 60 ] }]
}
}
},
{
$match: {
$and: [
{ "date": { $gte: ISODate("2018-01-10T10:00:00.000Z") } },
{ "date" : { $lte: ISODate("2018-01-30T23:30:00.000Z") } },
{ "minutes": { $gte: 60*10 } },
{ "minutes": { $lte: 23*60+30 } }
]
}
},
{
$project: { minutes: 0 }
}
])
You can do this with the following code.
db.getCollection('collection name').aggregate([
{$project: {
"yearMonthDayUTC": { $dateToString: { format: "%Y-%m-%d", date: "$date" }},
"timewithOffset": { $dateToString: { format: "%H:%M:%S", date: "$date", timezone: "Your time zone" }}
}
},
{$match: {
"yearMonthDayUTC": {$gte: "2018-01-10", $lt: "2018-01-30"},
"timewithOffset": {$gte: "10:00:00", $lt: "23:30:00"}
}}
])