Convert BSON ISODate to NumberLong in MongoDB - mongodb

I have a collection in MongoDB that has created fields with values currently stored as a BSON ISODate object. I want to convert all of those to NumberLong objects containing a timestamp.
First I tried this (in Mongo shell):
db.collection.find( { "created" : { "$type" : 9 } } ).forEach( function (x) {
x.created = new NumberLong(x.created);
db.collection.save(x);
});
JavaScript execution failed: Error: could not convert "Tue Mar 18 2014 18:11:21 GMT-0400 (EDT)" to NumberLong
Apparently a date string cannot be cast as a long...fair enough. Then I tried this, thinking I could make use of the Javascript Date object's UTC method:
db.collection.find( { "created" : { "$type" : 9 } } ).forEach( function (x) {
x.created = new Date(x.created).UTC();
db.collection.save(x);
});
JavaScript execution failed: TypeError: Object Tue Mar 18 2014 18:11:21 GMT-0400 (EDT) has no method 'UTC'
I've tried several other variations, but nothing has worked yet. Any help would be greatly appreciated!

To access the underlying numeric value of the Date, you can call getTime() on it:
x.created = new NumberLong(x.created.getTime());

The ISODate object has a "valueOf" method that will return an epoch time. Here is an example generating this via mongo shell:
replset:PRIMARY> var date = ISODate()
replset:PRIMARY> date
ISODate("2014-06-25T16:31:46.994Z")
replset:PRIMARY> date.valueOf()
1403713906994
replset:PRIMARY>

Related

mongodb date query don't work with ISODate?

I can find an item with this search:
db.item.find({"startdate":{$gte: 1485521569000 }})
The date seems to correspond to
> new Date(1485521569000)
ISODate("2017-01-27T12:52:49Z")
But if I search
db.item.find({"startdate":{"$gte" : ISODate("2017-01-01T00:00:00Z")}})
I don't get any results. What am I doing wrong?
PS
the only way I found is
db.item.find({"startdate":{"$gte" : (new Date("2017-01-01")).getTime()}})
is that right or there is a better way?
Below one will work.
db.getCollection('test').find({
"key": {
"$gte": (ISODate("2017-01-01")).getTime()
}
})
Reason:
You have your data is in int64 or long
In the new Date query, you are converting date to time which return int. So get performs integer comparison.
In ISODate you are passing a date, it doesn't convert date to integer i.e milliseconds. So if you convert, both will work.
new Date() returns the current date as a Date object. The mongo shell wraps the Date object with the ISODate helper
var d = ISODate("2017-01-01")
print(d); //Sun Jan 01 2017 05:30:00 GMT+0530 (IST)
Hence, the comparison fails.
If i understand, you have timestamp in startdate field,
This is the option if helps you, Can do it with aggregate() function, using $toDate,
$toDate convert timestamp to ISO date
db.collection.aggregate([
{
$match: {
$expr: {
$gte: [
{
$toDate: "$startdate"
},
ISODate("2017-01-27T12:52:49.000Z")
]
}
}
}
])
Playground: https://mongoplayground.net/p/H7SFHsgOcCu

How could I parse string into Date type "1998/10/01", "1998/1/01" format YYYY/M/D

How could I parse string into Date type "1998/10/01", "1998/1/01" format YYYY/M/D,
the tricky part is in month, this field maybe 2 digit for 10~12 or 1 digit for 1~9.
Is it possible to parse the kind of date string in mongo ?
like Date("$date_str")
Yes, with Javascript.
Assume I have the following document
{
"_id" : ObjectId("553a6abb3614af9afd23310c"),
"foo" : "bar",
"date" : "1998/10/01"
}
Note that date is a string. We can run the following JavaScript in Mongo Shell to update this to become a Date Object.
db.test.find().forEach( function(doc) {
if( typeof doc.date != 'undefined' ) { //There is a date property
var doc_date = doc.date.split("/"); //Explode on the `/`
doc.date = new Date(doc_date[0], doc_date[1], doc_date[2]); //Overwrite current value with Date Object
db.test.save(doc); //Save this document
}
});
And our document will now have the Date object;
{
"_id" : ObjectId("553a6abb3614af9afd23310c"),
"foo" : "bar",
"date" : ISODate("1998-11-01T00:00:00.000Z")
}
It's quite easy to get a date object from such a date string format YYYY/M/D; just pass the string as the parameter to the Date object on creation. These two simple tests confirm this:
var d1 = new Date("1998/10/01"),
d2 = new Date("1998/1/01");
console.log(d1); // Thu Oct 01 1998 00:00:00 GMT+0100 (GMT Daylight Time)
console.log(d2); // Thu Jan 01 1998 00:00:00 GMT+0000 (GMT Standard Time)
For relatively small datasets, you can then use the mongo's forEach() cursor method to do an atomic update with the $set operator :
db.collection.find().forEach(function(doc) {
db.collection.update(
{"_id": doc._id},
{
"$set": {
"date": new Date(doc.date)
}
}
);
});
Thanks for yours answer.
we should minus 1 on month, to get the correct Date.
db[collection].find().forEach( function(doc) {
if( typeof doc._id != 'undefined' ) { //There is a date property
var doc_date = doc._id.split("/"); //Explode on the `/`
doc.date = new Date(doc_date[0], doc_date[1]-1, doc_date[2]); //Overwrite current value with Date Object
doc.date = new Date(doc._id); //Overwrite current value with Date Object
db[collection].save(doc); //Save this document
}
});

mongo shell: how can I return a date stored in ms formated in a readable form?

I have a mongoDB with dates stored as ms.
when I query the DB with:
> db.drives.find({deviceID:4},{driveDate:1})
I get
{ "_id" : ObjectId("52725be3a3d27f8c9eee4022"), "driveDate" : 1383226033496 }
I want to display this date within the result in the mongoshell in a readable format. Is there a way to 'convert the date on the fly', so that the result will look like this?:
{ "_id" : ObjectId("52725be3a3d27f8c9eee4022"), "driveDate" : 'Thu Oct 31 2013 07:27:13 GMT-0600 (CST)' }
Thanks.
In MongoDB shell you can use this:
db.drives.find({deviceID:4},{driveDate:1}).forEach(function (doc) {
doc["driveDate"] = new Date(doc["driveDate"])
printjson(doc)
});

Remove old records in mongodb based on Month

I am trying to delete Older records present in my collection .
I have a collection named "user_track" , which consists of data in this format shown below
db.user_track.find().pretty()
{
"_id" : ObjectId("50c9afe5765fb0e4fea076ce"),
"cust_id" : "ddddd",
"symbol" : "WWWW",
"access_time" : "Thu Dec 13 2012 05:37:25 GMT-0500 (EST)"
}
{
"_id" : ObjectId("50c9afe7765fb0e4ffa076ce"),
"cust_id" : "eeeeeeeeee",
"symbol" : "WFC",
"access_time" : "Thu Dec 13 2012 05:37:27 GMT-0500 (EST)"
}
{
"_id" : ObjectId("522de3ae2191b0e41a7534dd"),
"cust_id" : "dsdsds",
"symbol" : "APPLE",
"access_time" : "Mon Sep 09 2013 11:05:18 GMT-0400 (EDT)"
}
In my collection , user_track , i want to keep only the current month's data (that is from Sep 01 2013 to current day ) and want to delete the rest of the records which doesn't belong to current month
I have tried to issue the below command , but i am not sure of how to issue this command to suit my requirement as the date i have is in different format .
db.user_track.delete( { 'access_time': {$lte: XXX} })
Please suggest .
You can give any Date with Javascript date
db.user_track.remove( { access_time : {"$lt" : new Date(year, month_0_indexed, day)} })
So for removing documents before 1 September 2013 your command should be
db.user_track.remove( { access_time : {"$lt" : new Date(2013, 8, 1) } })
September is the 9th month but the month field is zero indexed. So we make that as 8.
Mongo has a TTL feature on collections, I think this is a nice solution to such cases:
https://docs.mongodb.com/manual/tutorial/expire-data/
Basically something like:
db.log_events.createIndex( { "createdAt": 1 }, { expireAfterSeconds:
3600 } )
In addition to other answers you may be interesting in the "Time to live” collection feature:
http://docs.mongodb.org/manual/tutorial/expire-data/
It's useful to automatically expire/remove documents from a collection after specific period of time.
Probably there is a cleaner solution but this should work:
Create new Data field from date strings:
var cursor = db.user_track.find()
while (cursor.hasNext()) {
var doc = cursor.next();
db.user_track.update(
{_id : doc._id},
{$set : {access_time_ : new Date(doc.access_time)}})
}
Now you can retrieve some records by comparing dates:
db.user_track.find({access_time_: {$lt: new Date("Sep 01 2013 00:00:00 GMT+00:00")}})
If everything works as expected remove obsolete records:
db.user_track.remove({access_time_: {$lt: new Date("Sep 01 2013 00:00:00 GMT+00:00")}})
In the future use date objects not strings
I have found a solution to address this issue .
var date=new Date();
date.setDate(date.getDate() - 1);
db.user_track.remove({"access_time":{"$lt":date}});
I will make this run automatically by putting these lines in a bash file and scheduling that script using a cron tab .
Please share your views if this is a valid solution or not ??

MongoDB: How can I run a function for a certain field on all values in a collection?

I would like to do this from the mongo shell. Basically I want to change the way times are stored in my current database.
Right now my 'time' field is storing a string that looks like 'Thu Oct 11 2012 15:27:58 GMT-0500 (CDT)', but I would like to run a Date.parse('Thu Oct 11 2012 15:27:58 GMT-0500 (CDT)') so that the unix timestamp is stored instead.
I want to do this across the board for all current entries since I will just be using the unix timestamp in the future.
Thanks
How about:
var c = db.collection.find();
while (c.hasNext()) {
object = c.next();
time = Date.parse(object.time);
db.collection.update({_id: object._id}, {$set: {'time': time}});
}
Before executing it, I had the following:
db.times.find()
{ "_id" : ObjectId("50773daa77f428a7e4cd226b"), "time" : "Thu Oct 11 2012 15:27:58 GMT-0500 (CDT)" }
After executing it, it looks like this:
db.times.find()
{ "_id" : ObjectId("50773daa77f428a7e4cd226b"), "time" : 1349987278000 }
Hope this helps!