50

I need some help finding a record by date in mongodb and nodejs.

I add the date to the json object in a scraping script as follows:

jsonObj.last_updated = new Date();

This object is inserted into mongodb. I can see it as follows:

 "last_updated" : "2014-01-22T14:56:59.301Z"

Then in my nodejs script I do a findOne():

 var jObj = JSON.parse(line.toString());

 collection.findOne(jObj,function(err, doc) {
   if (doc){
     console.log(doc._id);
   } else  {
     console.log('not found');
   }
 });

The object is not found. If I remove the last_updated field from the object it is found so it is definitely where the problem is.

If I isolate the field as follows:

collection.findOne({last_updated: '2014-01-22T14:56:59.301Z'},function(err, doc) {
  if (doc){
    console.log(doc._id);
  } else  {
    console.log('not found');
  }
});

Nothing comes back either. What am I doing wrong please?

A-Sharabiani
  • 17,750
  • 17
  • 113
  • 128
jeh
  • 2,373
  • 4
  • 23
  • 38

5 Answers5

82

You need to pass a date object and not a date string.

collection.findOne({last_updated: new Date('2014-01-22T14:56:59.301Z')},function(err, doc) {

The MongoDB driver will transform it into ISODate:

{ 
   "_id" : ObjectId("52dfe0c469631792dba51770"), 
   "last_updated" : ISODate('2014-01-22T14:56:59.301Z') 
}

Check these questions:

Community
  • 1
  • 1
Ilan Frumer
  • 32,059
  • 8
  • 70
  • 84
  • 2
    Combining with momentjs `Items.find({sellingState: "Active", endTime: {$lt: new Date(moment().subtract(1, 'day').toISOString())}}, {limit: 10})` – Quake1TF Feb 11 '16 at 08:27
  • 1
    To store now use `new Date` without the parens – tim-phillips May 17 '16 at 17:18
  • Yup. Do **not** use ```new Date().toISOString()``` when inserting into MongoDB database (instead just use ```new Date()```) because MongDB already does the conversion for you and .toISOString() will make .find() operators or $gte operators on the database fail – Yi Xiang Chong Apr 15 '20 at 11:23
  • Using `new Date` without the parentheses (using Node 12.18 and mongo 3.4.1) gives me the same result in the document (a UTC ISODate) as using it with the parentheses, i.e. `new Date()` – Toomy Jun 03 '21 at 08:57
14

To clarify. What is important to know is that:

  • Yes, you have to pass a Javascript Date object.
  • Yes, it has to be ISODate friendly
  • Yes, from my experience getting this to work, you need to manipulate the date to ISO
  • Yes, working with dates is generally always a tedious process, and mongo is no exception

Here is a working snippet of code, where we do a little bit of date manipulation to ensure Mongo can handle it correctly. In this example, I am using mongoose module and want results for rows whose date attribute is less than (ie. before) the date given as myDate param.

var inputDate = new Date(myDate.toISOString());
MyModel.find({
    'date': { $lte: inputDate }
})
arcseldon
  • 35,523
  • 17
  • 121
  • 125
  • 3
    how does the myDate param look like ? Is it the string 'Mon Feb 29 2016 21:04:59 GMT+0100 (CET)' ? – Matko Feb 29 '16 at 20:07
  • I believe this is incorrect and made the same mistake which caused errors in my existing database. Do **not** use ```new Date().toISOString()``` when inserting into MongoDB database (instead just use ```new Date()```) because MongDB already does the conversion for you and .toISOString() will make .find() operators or $gte operators on the database fail – Yi Xiang Chong Apr 15 '20 at 11:24
7

I recently ran into the same issue and I wanted to add some additional info.

You can insert dates in two ways:

  1. Created on the nodejs server side (e.g. in a ExpressJS script)

example: insert a new object and time stamp it

db.collection('mycollection').findOneAndUpdate({'name': req.body.name}, {
  // only "update" if it's an insert, meaning name is not found
  $setOnInsert: {
    'name': req.body.name,
    'date_added': new Date()
  }
}, { 
  upsert: true
}, (err, result) => {
  if(err) return res.send(err);
  res.send(result);
});
  1. Created on the client side from JS and then sent over the wire using a REST API in a JSON object via a POST request

example:

// Send POST Request here
fetch('addDate', {
  method: 'post',
  headers: {'Content-Type': 'application/json'},
  body: JSON.stringify({
    'date_added':  new Date()
  })
})

For 1. and 2. you create the dates using the new Date('2014-01-22T14:56:59.301Z') function as explained in the answers above. The difference is that if you do it as in 1. on the server side using the MongoClient package it is stored as a ISODate('2014-01-22T14:56:59.301Z') in MongoDB. If you do it as in 2. on the client side it is stored as a String: '2014-01-22T14:56:59.301Z' in MongoDB.

To query the ISODate object you need to use new Date('2014-01-22T14:56:59.301Z') or ISODate('2014-01-22T14:56:59.301Z') To query the string you use just the string: '2014-01-22T14:56:59.301Z'

Here are some query samples using the mongo shell:

Date stored as String:

db.mycollection.findOne({date_added {$gte:'2018-06-22T00:07:53.688Z'}})

This returns

{
  "_id" : ObjectId("5b2c3dd90078ce3cd484ef21"),
  "name" : "alfons",
  "date_added" : "2018-06-22T00:07:53.688Z"
}

Date stored as ISODate:

db.mycollection.findOne({date_added: {$lte: ISODate('2018-06-26T23:24:37.023Z')}})

or using "new Date" instead:

db.mycollection.findOne({date_added: {$lte: new Date('2018-06-26T23:24:37.023Z')}

This returns:

{
  "_id" : ObjectId("5b2bb21e1954b104e61ff735"),
  "name" : "ceasar",
  "date_added" : ISODate("2018-06-21T14:11:41.323Z")
}
Renato
  • 141
  • 2
  • 4
1

add Default key in Schema and value to Date.now()

-1

If your using timestamps data to query. EG : "createdAt" : "2021-07-12T16:06:34.949Z"

const start  = req.params.id; //2021-07-12
const data = await Model.find({
            "createdAt": {
              '$gte': `${start}T00:00:00.000Z`,
              '$lt': `${start}T23:59:59.999Z`
            }
          });
console.log(data);

it will show the data of particular date .i.,e in this case. "2021-07-12"

sai krishna
  • 131
  • 5