Doing range queries in Mongoose for Hour / Day / Month/ Year - mongodb

Trying to figure out how to do this. Basically I want to sort by Hour / Day / Month / Year of my submissions.
Each submission has a created field which contains a Mongoose Date object in the form of "created" : ISODate("2013-03-11T01:49:09.421Z"). Do I need to compare against this in the find() conditions?
Here is my current query (I'm wrapping it in a count for pagination purposes FWIW so just ignore that part):
getSubmissionCount({}, function(count) {
// Sort by the range
switch (range) {
case 'today':
range = now.getTime();
case 'week':
range = now.getTime() - 7;
case 'month':
range = now.getTime() - 31; // TODO: make this find the current month and # of days in it
case 'year':
range = now.getTime() - 365;
case 'default':
range = now.getTime();
}
Submission.find({
}).skip(skip)
.sort('score', 'descending')
.sort('created', 'descending')
.limit(limit)
.execFind(function(err, submissions) {
if (err) {
callback(err);
}
if (submissions) {
callback(null, submissions, count);
}
});
});
Can someone help me figure this out? With that current code it just gives me all submissions regardless of a time range, so I'm obviously not doing something properly

I think, you are looking $lt(Less than) and $gt(Greater Than) operators in MongoDB.
By using above operators the result can be queried according to time.
I am adding possible solution below.
var d = new Date(),
hour = d.getHours(),
min = d.getMinutes(),
month = d.getMonth(),
year = d.getFullYear(),
sec = d.getSeconds(),
day = d.getDate();
Submission.find({
/* First Case: Hour */
created: { $lt: new Date(), $gt: new Date(year+','+month+','+day+','+hour+','+min+','+sec) } // Get results from start of current hour to current time.
/* Second Case: Day */
created: { $lt: new Date(), $gt: new Date(year+','+month+','+day) } // Get results from start of current day to current time.
/* Third Case: Month */
created: { $lt: new Date(), $gt: new Date(year+','+month) } // Get results from start of current month to current time.
/* Fourth Case: Year */
created: { $lt: new Date(), $gt: new Date(year) } // Get results from start of current year to current time.
})

Related

How to compare two dates with Mongodb (find query using NestJS)

I'm trying to get the list of posts for which the publish date is equal or less than the current date.
I'm using NestJS, Mongo & typeORM; which syntax should I use?
const posts =
await this.mbRepository.find(
{ where: { "deletedAt": null , "publishDate" <= currentDate } }
);
let firstPoint = new Date();
firstPoint.setHours(0);
firstPoint.setMinutes(0);
firstPoint.setSeconds(0);
let lastPoint = new Date();
lastPoint.setHours(23);
lastPoint.setMinutes(59);
lastPoint.setSeconds(59);
const posts = await this.mbRepository.find({ publishDate: { $gte: firstPoint, $lt: lastPoint } } });
Get current day and make two point. One as begining of the day and another as end of the day. Then you can use mongodb operator $gte and $lt. In this way you will get all post which have been publish in this time range.

MongoDB query with subtraction on time not working?

{'field.timestamp': {'$lt': Date()}, 'field.timestamp': {'$gt': new Date(ISODate().getTime() - 1000 * 60 * 60) } }
returns:
"JSON parsing error: Invalid date format at line 1, col 83"
You forgot the new keyword as well as duplicating keys 'field.timestamp'. If you are querying a date range from now and 15 days ago, then the correct query should be:
var fifteenDaysAgo = new Date(),
today = new Date();
fifteenDaysAgo.setDate(fifteenDaysAgo.getDate() - 15);
db.my_collection.find({ 'field.timestamp': { '$lt': today, '$gt': fifteenDaysAgo } });

meteorhacks:aggregate to group mongo documents

This Meteor server code tries to count all the records which are 4 months and newer with property size:'4', color:'white' but account all entires from any one user as one count, so no mater how many documents have been entered by the same user, the are all counted as one. but I am getting nothing in return. any ideas? thx
let date = new Date();
date.setMonth(date.getMonth() - 4);
let doc = UsageCol.aggregate([{
$match: {
createdAt: {
$gte: date,
$lte: new Date()
},
action: 'failBroadcast',
plate: plate
}
}, {
$group: {
_id: {
userId: "$userId"
},
count: {
$sum: 1
}
}
}]);
for (var i = 0; i < doc.length; i++) {
var obj = doc[i];
console.log(JSON.stringify(obj));
}
Alright I just wanted to clear some things up from this morning.
The only reason I recommended moment js was thinking we are storing the date in date type and there is no easy way to dynamically create date in UTC using java script date function
So now that we know you used Date.now() to save the dates, you don't need any moment js.
The correct syntax is
let dateToMillis = Date.now(); //The current millis from epoch.
let dateFrom = new Date(dateToMillis); // Use the current millis from epoch.
let dateFromMillis = dateFrom.setMonth(dateFrom.getMonth() - 4); // The millis 4 months ago from epoch.
Pass dateToMillis and dateFromMillis to aggregation query.

Convert dates from String format to Date format in mongodb

I have my birthDate in string format like this "2010-03-22". I want to convert it in the Date type in MongoDB.
What db.patient.update() function should I write ?
I want to calculate the age of each person.
I used the solution give on How do I convert a property in MongoDB from text to date type? but all the dates got converted to "1970-01-01T00:00:00.000Z".
db.collection.find().forEach(function(e){
e.fieldname = new Date(e.fieldname)
db.collection.save(e)
});
If you are using robomonogo use new ISODate instead of new Date
One approach you could take in converting the field to the correct date object would be by splitting the string on the given delimiter "-". Use parseInt() to convert the delimited strings into numbers, and the new Date() constructor builds a Date from those parts: the first part will be the year, the second part the month, and the last part the day. Since Date uses zero-based month numbers you have to subtract one from the month number.
The following demonstrates this approach:
var cursor = db.patient.find({"birthDate": {"$exists": true, "$type": 2 }});
while (cursor.hasNext()) {
var doc = cursor.next();
var parts = doc.birthDate.split("-");
var dt = new Date(
parseInt(parts[0], 10), // year
parseInt(parts[1], 10) - 1, // month
parseInt(parts[2], 10) // day
);
db.patient.update(
{"_id": doc._id},
{"$set": {"birthDate": dt}}
)
};
For improved performance especially when dealing with large collections, take advantage of using the Bulk API for bulk updates as you will be sending the operations to the server in batches of say 500 which gives you a better performance as you are not sending every request to the server, just once in every 500 requests.
The following demonstrates this approach, the first example uses the Bulk API available in MongoDB versions >= 2.6 and < 3.2. It updates all
the documents in the collection by changing the OrderDate fields to date fields:
var bulk = db.patient.initializeUnorderedBulkOp(),
counter = 0;
db.patient.find({"birthDate": {"$exists": true, "$type": 2 }}).forEach(function (doc) {
var parts = doc.birthDate.split("-");
var dt = new Date(
parseInt(parts[0], 10), // year
parseInt(parts[1], 10) - 1, // month
parseInt(parts[2], 10) // day
);
bulk.find({ "_id": doc._id }).updateOne({
"$set": { "birthDate": dt}
});
counter++;
if (counter % 500 == 0) {
bulk.execute(); // Execute per 500 operations and re-initialize every 500 update statements
bulk = db.patient.initializeUnorderedBulkOp();
}
})
// Clean up remaining operations in queue
if (counter % 500 != 0) { bulk.execute(); }
The next example applies to the new MongoDB version 3.2 which has since deprecated the Bulk API and provided a newer set of apis using bulkWrite():
var bulkOps = db.patient.find({"birthDate": {"$exists": true, "$type": 2 }}).map(function (doc) {
var parts = doc.birthDate.split("-");
var dt = new Date(
parseInt(parts[0], 10), // year
parseInt(parts[1], 10) - 1, // month
parseInt(parts[2], 10) // day
);
return {
"updateOne": {
"filter": { "_id": doc._id } ,
"update": { "$set": { "birthDate": dt } }
}
};
})
db.patient.bulkWrite(bulkOps);

Date Range Mongo Query using Meteor Js

I have an attribute in my collection called dateacquired and the date is formatted like: 2014-03-28 06:08:00.
I am needing to pull back all documents in my collection that are less than or equal to a month ago from the current date. I am just not sure how to write this query.
Anyone know how to start one something like this?
I assume those dates are stored as strings? You can compare strings with the mongoDB comparison operators $gt or $lt and they work as you’d expect. I’m going to also use Sugar to make my life easier (highly recommended; add via mrt add sugarjs) which gives me the Date.create and Date.format methods which reduce this into a one-liner:
var cursorOfDocumentsSinceOneMonthAgo = yourCollection.find({
dateacquired:
{ $gt: Date.create("1 month ago").format("{yyyy}-{MM}-{dd} {hh}:{mm}:{ss}")
}
});
My meteor method for how many people have signed up in the last nDays:
userCountPreviousDays: function (nDays) {
check(nDays, Number);
var arr = [];
var now = new Date().getTime();
var msInDay = 1000 * 60 * 60 * 24;
for (var i = 0; i < nDays; i++) {
arr[i] = Meteor.users.find({
createdAt: {
$lt: new Date(now - (msInDay * i)),
$gt: new Date(now - (msInDay * (i+1)))
}
}).count();
};
return arr;
}
arr[i] is how many people signed up i days ago.