how to check a date is less than today date in mongoose? - mongodb

my collection in db is
plannedEndDate:{"2020-03-10T11:22:33.677+00:00"}
in controller var tdate= new Date(); [tdate is in the format 2020-03-10T14:28:22.687Z].
now,I need to check plannedEndDate is less than tdate in mongoose.
i tried,
plannedEndCmp: {
$cond: [{ $lt: ["$plannedEndDate", tdate] }, 1, 0]
}
but it is not returning true.
so should i need to trim the timestamp to compare dates in mangodb?or should i need to convert date into common format?

Not clear what you actually like to do but below command find the document or show indication:
db.collection.find(
{ plannedEndDate: { $lt: tdate } }
)
db.collection.aggregate([
{ $set: { plannedEndCmp: { $cond: [{ $lt: ["$plannedEndDate", tdate] }, 1, 0] } } },
{ $set: { plannedEndCmp_bool: { $lt: ["$plannedEndDate", tdate] } } }
])

In Aggregate group:
`
factualEndDate: {
"$dateToString": { "format": "%Y-%m-%d", "date": "$factualEndDate" }
},
In Aggregate project:
DelayedComplete: { $cond: [
{
$and: [
{ $cond: [{ $lte: [{ $max: "$data.factualEndDate" }, today] }, 1, 0] },
]
},
1,
0
]
},
`

Related

MongoDB: Add date comparison to arrayFilters

Objects of my collection have a field, that is an array of objects with one of the field being a string date
{
citizens: [{
name: 'John'
birthday: '1993/07/13'
},
{
name: 'Sarah'
birthday: '1996/07/13'
},
{
name: 'Natalia',
birthday: '2015/07/13'
}]
}
{
citizens: [{
name: 'Leo'
birthday: '1994/02/08'
},
{
name: 'Paul'
birthday: '1934/09/13'
},
{
name: 'Rego',
birthday: '2019/01/29'
}]
}
I want to set to all the users older than 18 status 'adult'
Here is what I try to do:
users.updateMany({}, {
$set: { 'citizens.$[elem].status': 'adult' },
},
{
arrayFilters: [
{ 'elem.status': { $exists: false } },
{ $lt: [{ $toDate: 'elem.$birthday' }, 18yearsaAgoDate] }, <-- 18years don't mean much here, I actually use $$NOW
],
multi: true,
});
But I get 'unknown top level operator: $lt' error when run this. How do I supposed to use $lt in arrayFilter?
Thanks in advance!
Here's how you could do it in a simple update using the aggregation pipelined updates:
db.collection.updateMany({},
[
{
$set: {
citizens: {
$map: {
input: "$citizens",
in: {
$mergeObjects: [
{
status: {
$cond: [
{
$gt: [
{
$dateDiff: {
startDate: {
$toDate: "$$this.birthday"
},
endDate: "$$NOW",
unit: "year"
}
},
18
]
},
"adult",
"$$REMOVE"
]
}
},
"$$this"
]
}
}
}
}
}
])
Mongo Playground
I've used some version 5+ operators like $dateDiff as it makes the code cleaner, but you could still achieve the same results without them using $subtract and a constant for 18 years, like so:
{
$lt: [
{
$toDate: "$$this.birthday"
},
{
$subtract: [
"$$NOW",
567648000000// 18 years in miliseconds
]
}
]
}
Mongo Playground
This is an update using the arrayFilters syntax.
db.collection.updateMany(
{ },
{
$set: { "citizens.$[elem].status": "adult" }
},
{
arrayFilters: [ { "elem.status": { $exists: false } , "elem.birthday": { $lt: "2004/07/27" } } ]
}
)
Note the date value "2004/07/27" is the day 18 years ago (very close approximate value). And using string values in date comparison requires that the value is formatted in "YYYY/mm/dd".
It would have worked like this if your date was already in the right format. Since you need to format it, I think you should use an aggregation pipeline with a $merge stage:
db.collection.aggregate([
{$set: {
citizens: {
$map: {
input: "$citizens",
in: {$mergeObjects: [
{status: {
$cond: [
{$lt: [{$toDate: "$$this.birthday"}, 18yearsaAgoDate]},
"adult",
"$$REMOVE"
]
}
},
"$$this"
]
}
}
}
}
},
{ $merge : { into : "collection" } }
])
See how it works on the playground example

MongoDB: Search by field with date and update it by condition

Please tell me how can I fulfill the following condition - if the time in the info.startDate field is not equal to 00 hours, increase the date (2021-05-27) by 1 day ahead, set the time to 00:00:00.000Z. I tried to do it clumsily, through Mongock, getting all the elements of the collection and doing a check through LocalDateTime, but my heap overflowed, which is logical because the collection is large. How can I do this through Mongock or at least a manual request to MongoDB. So far I've only written this:
db.getSiblingDB("ervk_core").getCollection("supervision").updateMany(
{},
[
{
"$set": {
"info.startDate": {
"$cond": {
if: {
$eq: [
"$info.startDate",
(there should be a condition at midnight)
]
},
then: (here the day should be added to full and the time should be set to midnight)
}
}
}
}
])
I would like to use dateToString to do a partial search by hour, but as I understand it, this function can only be used in an aggregation.
I would be grateful for your help :)
If you're using Mongo version 5.0+ then you can use $dateTrunc and $dateAdd to achieve this quite easily, like so:
db.collection.updateMany(
{},
[
{
$set: {
"info.startDate": {
$cond: [
{
$ne: [
{
$hour: "$info.startDate"
},
0
]
},
{
$dateTrunc: {
date: {
$dateAdd: {
startDate: "$info.startDate",
unit: "day",
amount: 1
}
},
unit: "day",
}
},
"$info.startDate"
]
}
}
}
])
For older Mongo versions this is slightly messier, you should use $dateFromParts to create the new date object, like so:
db.collection.updateMany(
{},
[
{
$set: {
"info.startDate": {
$cond: [
{
$ne: [
{
$hour: "$info.startDate"
},
0
]
},
{
$dateFromParts: {
"year": {
$year: {
$add: [
"$info.startDate",
86400000
]
}
},
"month": {
$month: {
$add: [
"$info.startDate",
86400000
]
}
},
"day": {
$dayOfMonth: {
$add: [
"$info.startDate",
86400000
]
}
},
"hour": 0,
"minute": 0,
"second": 0,
"millisecond": 0,
}
},
"$info.startDate"
]
}
}
}
])
Mongo Playground

Mongodb aggregation , group by items for the last 5 days

I'm trying to get the result in some form using mongodb aggregation.
here is my sample document in the collection:
[{
"_id": "34243243243",
"workType": "TESTWORK1",
"assignedDate":ISODate("2021-02-22T00:00:00Z"),
"status":"Completed",
},
{
"_id": "34243243244",
"workType": "TESTWORK2",
"assignedDate":ISODate("2021-02-21T00:00:00Z"),
"status":"Completed",
},
{
"_id": "34243243245",
"workType": "TESTWORK3",
"assignedDate":ISODate("2021-02-20T00:00:00Z"),
"status":"InProgress",
}...]
I need to group last 5 days data in an array by workType count having staus completed.
Expected result:
{_id: "TESTWORK1" , value: [1,0,4,2,3] ,
_id: "TESTWORK2" , value: [3,9,,3,5],
_id : "TESTWORK3", value: [,,,3,5]}
Here is what I'm trying to do, but not sure how to get the expected result.
db.testcollection.aggregate([
{$match:{"status":"Completed"}},
{$project: {_id:0,
assignedSince:{$divide:[{$subtract:[new Date(),$assignedDate]},86400000]},
workType:1
}
},
{$match:{"assignedSince":{"lte":5}}},
{$group : { _id:"workType", test :{$push:{day:"$assignedSince"}}}}
])
result: {_id:"TESTWORK1": test:[{5},{3}]} - here I'm getting the day , but I need the count of the workTypes on that day.
Is there any easy way to do this? Any help would be really appreciated.
Try this:
db.testcollection.aggregate([
{
$match: { "status": "Completed" }
},
{
$project: {
_id: 0,
assignedDate: 1,
assignedSince: {
$toInt: {
$divide: [{ $subtract: [new Date(), "$assignedDate"] }, 86400000]
}
},
workType: 1
}
},
{
$match: { "assignedSince": { "$lte": 5 } }
},
{
$group: {
_id: {
workType: "$workType",
assignedDate: "$assignedDate"
},
count: { $sum: 1 }
}
},
{
$group: {
_id: "$_id.workType",
values: { $push: "$count" }
}
}
]);

Mongodb groupby range of date and id

I have a database
{
"_id": "222jMQDEHuHXTuDeF",
"customer_id": "QfdAFubKS9ytdbhbq",
"createdDate": {
"$date": "2020-07-27T08:19:40.791Z"
}
},
{
"_id": "278jKLDEHuHXItDeF",
"customer_id": "HtdAFubJS8ytdnjbe",
"createdDate": {
"$date": "2020-07-26T08:19:40.791Z"
}
},
{
"_id": "128lRLDEHuHXItPhy",
"customer_id": "KodATubJS8yyqkjbe",
"createdDate": {
"$date": "2020-07-25T08:19:40.791Z"
}
}
I need to get data of the previous week where current date is the end date and group by date and customer_id and get the count of customer_id in mongodb.
You can compare like following. For the easiness I have added previouseWeekStart, but you can directly call it inside the $match stage instead of using $addFields. This should definitely work, but I can't show a demo in mongoplayground since I have added subtract symbol (-) for calculating previous date.
db.collection.aggregate([
{
$addFields: {
previouseWeekStart: new Date(new Date()-7*60*60*24*1000)
}
},
{
$match: {
$expr: {
$and: [
{
$gt: [
"$createdDate",
"$previouseWeekStart"
]
},
{
$lt: [
"$createdDate",
new Date()
]
}
]
}
}
},
{
$group: {
_id: {
cusId: "$customer_id",
date: "$createdDate"
},
count: {
$sum: 1
}
}
}
])

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
]
}
}
}
}