How to insert BSON-ified datetime?

911 views
Skip to first unread message

Evan Zamir

unread,
Jun 14, 2013, 11:09:04 PM6/14/13
to node-mong...@googlegroups.com
I want to be able to do aggregation with dates, and I have gotten it to work using the Ruby driver, but not the Node driver. Currently, my code looks like:

var query = {};
var date = new Date();
query['datetime'] = date;
Db.connect(mongoUri, function (err, db) {
        if (!err) {
            db.collection(analyticsCollection, function (err, coll) {
                if (!err) {
                    coll.save(query, {safe:true}, function (err, result) {
                        db.close();
                        res.send(200,result);
                        //console.log(result);
                    });
                } else {
                    res.json(503,{errno:503,msg:'error: collection does not exist.'});
                }
            });
        } else {
            res.json(503,{errno:503,msg:'error: database does not exist.'});
        }
    });

When I try to do this aggregation:
db.analytics.aggregate([{$group:{_id:{day:{$dayOfMonth:"$datetime"}},count:{$sum:1}}}])

I get the following errors:
Fri Jun 14 19:45:21.104 JavaScript execution failed: aggregate failed: {
"errmsg" : "exception: can't convert from BSON type String to Date",
"code" : 16006,
"ok" : 0
} at src/mongo/shell/collection.js:L898

Any ideas about what's going on or how to do this correctly?

mike o'brien

unread,
Jun 14, 2013, 11:24:51 PM6/14/13
to node-mong...@googlegroups.com
Can you post a sample doc from your collection?
This part looks wrong: {$group:{_id:{day:{$dayOfMonth:"$datetime"}} 

You need to break this into two steps. First do a $project to apply the dayOfMonth function to a field, and then do the $group on that field.



--
You received this message because you are subscribed to the Google Groups "node-mongodb-native" group.
To unsubscribe from this group and stop receiving emails from it, send an email to node-mongodb-na...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Evan Zamir

unread,
Jun 14, 2013, 11:55:54 PM6/14/13
to node-mong...@googlegroups.com
The date field is simply:

"datetime""2013-06-15T03:14:01.755Z"

Is it the case that you have to use $project with the node driver? Because I was able to run this aggregation without project when I inserted documents with the Ruby driver.
-eva
To unsubscribe from this group and stop receiving emails from it, send an email to node-mongodb-native+unsub...@googlegroups.com.

mike o'brien

unread,
Jun 15, 2013, 12:09:24 AM6/15/13
to node-mong...@googlegroups.com
no, it doesn't matter what driver the documents were inserted with, as long as you are using the same structure.
try this:
db.analytics.aggregate([{$project:{day:{$dayOfMonth:"$datetime"}}},   {$group:{_id:"$day",count:{$sum:1}}}])

To unsubscribe from this group and stop receiving emails from it, send an email to node-mongodb-na...@googlegroups.com.

Evan Zamir

unread,
Jun 15, 2013, 12:38:24 AM6/15/13
to node-mong...@googlegroups.com
Ok, thanks. I tried that, but it still gives the sam error.
To unsubscribe from this group and stop receiving emails from it, send an email to node-mongodb-native+unsubscribe...@googlegroups.com.

For more options, visit https://groups.google.com/groups/opt_out.
 
 

Evan Zamir

unread,
Jun 15, 2013, 12:41:14 AM6/15/13
to node-mong...@googlegroups.com
I guess my real question is how are you actually supposed to insert a datetime that can be aggregated in this way? Am I currently doing it the right way or not?


On Friday, June 14, 2013 9:09:24 PM UTC-7, mpobrien wrote:
To unsubscribe from this group and stop receiving emails from it, send an email to node-mongodb-native+unsubscribe...@googlegroups.com.

For more options, visit https://groups.google.com/groups/opt_out.
 
 

mike o'brien

unread,
Jun 15, 2013, 12:55:10 AM6/15/13
to node-mong...@googlegroups.com
it looks like you're storing the date as a string, but you need to be storing an actual object of type Date. in node for example you can do:

new Date("2013-06-15T03:14:01.755Z")



To unsubscribe from this group and stop receiving emails from it, send an email to node-mongodb-na...@googlegroups.com.

Evan Zamir

unread,
Jun 15, 2013, 1:50:51 AM6/15/13
to node-mong...@googlegroups.com
But I'm currently using new Date() to get the current datetime. I thought that was the correct way to do it.

Evan Zamir

unread,
Jun 15, 2013, 1:58:34 PM6/15/13
to node-mong...@googlegroups.com

I found a way to do what I wanted to do. This seems kind of klugey to me, so if anyone can find a better way, please let me know. My solution uses the underscore.js library (also posted this on SO):

http://stackoverflow.com/questions/17118075/how-to-save-datetime-as-bson-date-using-node-driver/17126378#17126378

var _ = require('underscore');
vary query = {}
query['foo'] = 'bar'


Db.connect(mongoUri, function (err, db) {
        if (!err) {
            db.collection(analyticsCollection, function (err, coll) {
                if (!err) {

                    coll.save(_.extend(query,{"datetime":new Date()}), {safe:true}, function (err, result) {

                        db.close();
                        res.send(200,result);
                        //console.log(result);
                    });
                } else {
                    res.json(503,{errno:503,msg:'error: collection does not exist.'});
                }
            });
        } else {
            res.json(503,{errno:503,msg:'error: database does not exist.'});
        }
    });

Now I can do the aggregation (without needing to use the $project operator):

> db.analytics.aggregate([{$group:{_id:{day:{$dayOfMonth:"$datetime"}}}}])
{ "result" : [ { "_id" : { "day" : 15 } } ], "ok" : 1 }

Hope this helps someone.

Reply all
Reply to author
Forward
0 new messages