Mongo find next Tuesday - mongodb

I'm trying to get the next Tuesday (day 2 of ISO Week) from today on. I have the current date from the global var "$$NOW" and the current day of ISO Week by the following operator: { $dayOfWeek: "$$NOW" }. But I can't think of any way to get the date of the next Tuesday in MongoDB-Aggregation.
For example i have as Input:
"$$NOW" which is => new Date("2021-09-13T16:20:00Z") // Today Monday
And now I want to get the next Tuesday:
new Date("2021-09-14T16:20:00Z") // coming Tuesday
which is quite easy, but if there is a week shift, it gets a bit more difficult. If the NOW date would be:
"$$NOW" which is => new Date("2021-09-16T16:20:00Z") // coming Thursday would be Today
the next Tuesday would be the:
new Date("2021-09-21T16:20:00Z") // Tuesday next week
So I always want to get the next following Tuesday after Today.
At the end, I want to create a mongo pipeline like this:
[{
$addFields: {
"nextTuesday": new Date(" the date of the next Tuesday ")
}
}]
I would be very happy about any help!

MongoDB has the $dayOfWeek operator that returns 1 for Sunday, 7 for Saturday.
On that scale, the formula to find a desired day of the week would be:
(((desired_day + 6) - current_day) modulo 7) + 1
Which in the MongoDB aggregation language, would look like:
{$addFields:{
nextTuesday:{
$toDate:{
$add:[
"$$NOW",
{$multiply:[
86400000,
{$add:[
1,
{$mod:[
{$subtract:[
9,
{$dayOfWeek:"$$NOW"}
]},
7
]}
]}
]}
]
}
}
}}
Playground

Related

MongoDB 4.4: Compare particular date with an interval of other date

Basically what I want to do is to compare that the difference between 2 date is less than 1 year, i.e. scheduled_end < scheduled_start + 1 year
I'm trying to use the following expression, but it does not seem valid:
scheduled_end: {
$lt: {
$add: [scheduled_start, 365*24*60*60000 ]
}
}
How to fix it?
I'm using MongoDB 4.4, so $dateAdd is not available in this version.

Converting StringDate to a queryable representation. Group and project sum of today,yesterday, week, month

I was about to try to figure out how to complete the given question.
It might consists of 2 parts, first one being - my collection dates are stored in plain string with a mysql format (YYYY-mm-dd HH:mm:ss), the second how to project the (today, yesterday, 7 day, month - summaries).
I have been experimenting around and this is what I came up with.
Pipe 1.
$match - nothing fancy there just a simple field = value.
Pipe 2.
$addField - trying to process the string date as a ISO date I believe? I am not sure
{
expired: {
$dateFromString: {
dateString: '$expired',
timezone: 'America/New_York'
}
}
}
Pipe 3.
$match - Quoted out wanted to select only a specific range so not more than 30 days - doesn't work
expired: {
$gt: ISODate(new Date(new Date(ISODate().getTime() - 1000*60*60*24*30)))
}
Pipe 4.
$group - Here I group and sum everything per day. So an output is
_id: 2021-09-27, theVal : 100
{
_id: {
$dateToString: {
date: { $toDate: "$expired" },
format: "%Y-%m-%d" }
},
theVal : {$sum:{$first:"$values.quantity"}} // as $values is an array [0].quantity,[1].quantity,[2].quantity - I am just interested in the first element.
}
Pipe 5.
$project - getting rid of the _id field - making it date name field, keeping theVal.
{
"date": "$_id",
"theVal": 1,
"_id": 0
}
theVal is a sum of integers within a day.
Questions
Between Pipe 1 and 2 ( temporary 3 ) I should be able to match dates
within the last 30 days to reduce the processing?
How to get a desired output like this:
{
today : 100,
yesterday : 10,
7days : 220,
month: 1000,
}
Really appreciate any help here.
Tried to "replicate" what you intend to do as you didn't provided sample test data.
You may want to do the followings in an aggregation pipeline:
$match : filter out the ids you want - same as your pipe 1
$dateFromString: use "format": "%Y-%m-%d %H:%M:%S", "timezone": "America/New_York"
$match : filter out records that are within 30 days with $expr and $$NOW
$group : group by date without time; achieved by converting to dateString with date part only
$addFields : project flags that determine if the record are within today, ``yesterday, 7days, month`
$group : As you didn't provided what is the meaning of today, ``yesterday, 7days, month, I made an assumption that they are the cumulative sum in the ranges. Simply and conditional $sum` will do the summation with the help of flags in step 5
Here is a Mongo playground for your reference.

Differences between weekNumber in Mongo and Luxon

I am doing some mongo aggregations on dates and have run in to an interesting problem, namely that the $week returned from mongo is different than the weekNumber returned from Luxon.
In the below code snippets, the $week from mongo returns 47, whereas the weekNumber from Luxon returns 48.
Is there a way to normalize the two so that a given date will return the same $week/weekNumber?
I can subtract one from the value returned by Luxon, but I'd like to understand why the responses are different in order to determine if there is a more appropriate/elegant way to fix this.
MONGO:
[{
'$match': {
'date': {
'$eq': datetime(2020, 11, 23, 0, 0, 0, tzinfo=timezone.utc)
}
}
}, {
'$project': {
'w': {
'$week': '$date'
}
}
}]
LUXON:
import { DateTime } from "luxon";
var week = DateTime.fromJSDate(new Date(2020,10,23)).weekNumber;
console.log(week);
Have a look at documentation:
weekNumber:
Week calendar: For ISO week calendar attributes, see the weekYear, weekNumber, and weekday accessors.
$week:
Returns the week of the year for a date as a number between 0 and 53.
Weeks begin on Sundays, and week 1 begins with the first Sunday of the year. Days preceding the first Sunday of the year are in week 0. This behavior is the same as the “%U” operator to the strftime standard library function.
If you like to get to Week number according to ISO-8601 use $isoWeek():
Returns the week number in ISO 8601 format, ranging from 1 to 53. Week numbers start at 1 with the week (Monday through Sunday) that contains the year’s first Thursday.
Looks like in Luxon does not have an equivalent to MongoDB's $week

get a excluded day in a the month

I want to get all the data from the month in mongodb
lets say i want to get all the data from September, except 23 Sep
i think of
createdAt 1 sep AND createdAt not in 23,24 sep
but it only execute the createdAt not in 23,24 sep
is there other ways?
db.getCollection('myTest').find({
"$and":[{
createdAt:{ "$gte": ISODate("2019-09-01T16:00:00.000Z")},
createdAt:{ "$nin": [ISODate("2019-09-23T16:00:00.000Z"), ISODate("2019-09-24T16:00:00.000Z")]}
}]
})
db.test.aggregate([{$project:{date:"$date",month:{$month:"$date"},year:{$year:"$date"}}},{$match:{$and:[{date:{$nin:[ISODate("
2019-09-23T00:00:00Z")]}},{month:9},{year:2019}]}},{$project:{_id:1,date:"$date"}}])
])
To get the month number $month,$year operator gives month and year number
$nin for not in date and check month and year number to get particular month in a year
$project the required values

Mongoose query by current date

So I have a mongoose collection. This collection have a day property in it.
So let's say I have 3 documents in it:
{day: "2017-07-16T17:00:00.000Z"}
{day: "2017-07-17T17:00:00.000Z"}
{day: "2017-07-18T17:00:00.000Z"}
Each date has hardcoded 17:00 time in it. Consider this as the start time.
So let's say currentDate is 2017.07.17 and it's 16h. I need to return document that has day that is 16th, because of the time.
Next one starts in an hour, and in an hour I should be returning the 17th.
I tried:
Table.find({ day: { $lt: Date.now() } })
But this, on the 18th, still returns 16th.
How do I write this query so it returns document that is currently 'active' ?