Inserting and Querying Date with MongoDB and Nodejs
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?
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:
- MongoDB + nodejs : how to query ISODate fields?
- ISODate is not defined
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 }
})
I recently ran into the same issue and I wanted to add some additional info.
You can insert dates in two ways:
- 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);
});
- 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")
}