Nick Schroeder Nick Schroeder - 2 months ago 47
Node.js Question

Find by ISODate using Node.js, Express, and MongoDB

I'm using Node.js and Express on a webserver to query MongoDB on a dbserver and running into a problem getting the dates to work together, I've read a bunch of threads here about the problem, most notably this one:

Inserting and Querying Date with MongoDB and Nodejs

I'm pretty sure I understand what I'm supposed to be doing, but nothing I try seems to work.

In my .js file, I have the following:

var todayStart = new Date();
todayStart.setSeconds(0);
todayStart.setHours(0);
todayStart.setMinutes(0);
todayStart.setMilliseconds(0);

var todayEnd = new Date(todayStart);
todayEnd.setHours(23);
todayEnd.setMinutes(59);
todayEnd.setSeconds(59);
todayEnd.setMilliseconds(999);

var query = {
"date": {
$gte: new Date(todayStart).toISOString(),
$lte: new Date(todayEnd).toISOString()
}
};


My query var outputs to the console in the format I expect:

{ date:
{ '$gte': '2016-09-13T00:00:00.000Z',
'$lte': '2016-09-13T23:59:59.999Z' }
}


I attempt to use either my query variable or the date vars themselves, and both return a result of null (no errors):

db.collection('test').findOne(query, function(err, result) {
db.collection('test').findOne({"date" : {$gte: new Date(todayStart).toISOString(),$lte: new Date(todayEnd).toISOString() }}, function(err, result) {


However if I just plug in my dates like so, it returns my result:

db.collection('test').findOne({"date" : {$gte: new Date("2016-09-13T00:00:00.000Z"),$lte: new Date("2016-09-13T23:59:59.999Z") }}, function(err, result) {


Any idea what I'm missing here?

Answer

No need to cast the dates to an ISO string format, just query using the JS dates. For a detailed explanation why, refer to the documentation.

Your start date object should hold the current date time hours at 00:00:00.000 (milliseconds precision) and set the hours for today's date to 23:59:59.999 to the end date variable:

var todayStart = new Date();
todayStart.setHours(0,0,0,0);

var todayEnd = new Date();
todayEnd.setHours(23,59,59,999);

var query = {
    "date": {
        $gte: todayStart,
        $lte: todayEnd
    }
};

db.collection('test').findOne(query, function(err, result) {
    if (err) throw new Error();
    console.log(JSON.stringify(result));
});

If you are using the momentjs library, this can be done by using the startOf() and endOf() methods on the moment's current date object, passing the string 'day' as arguments:

var todayStart = moment().startOf('day'); // set to 12:00 am today
var todayEnd = moment().endOf('day'); // set to 23:59 pm today