convert milliseconds to date in mongodb aggregation pipeline for group by?
I'm trying to get the logic behind converting the txnTime
field to a date object because grouping by either a date field or a timestamp in milliseconds (like what you are presently doing) will yield the same result as they both are unique in their respective formats!
To change the txnTime
field to a date object you should then include a $project
pipeline before the $group
pipeline stage with this expression
"txnTime": {
"$add": [ new Date(0), "$txnTime" ]
}
so that you can do your $group
operation on the converted/projected txnTime field:
var convertedTxnTime = { "$add": [new Date(0), "$txnTime"] };
/*
If using MongoDB 4.0 and newer, use $toDate
var convertedTxnTime = { "$toDate": "$txnTime" };
or $convert
var convertedTxnTime = { "$convert": { "input": "$txnTime", "to": "date" } };
*/
db.campaign_wallet.aggregate([
{ "$match": {
"campaignId" : 1 ,
"txnTime" : {
"$gte" : 1429554600000 ,
"$lte" : 1430159400000
}
} },
{ "$group" : {
"_id" : {
"txnTime": convertedTxnTime,
"msisdn" : "$msisdn"
},
"msisdnCount" : { "$sum" : 1}
} }
]);
Output: (based on the sample documents from this question)
/* 0 */
{
"result" : [
{
"_id" : {
"txnTime" : ISODate("2015-04-25T18:30:00.000Z"),
"msisdn" : "91808770101"
},
"msisdnCount" : 1
},
{
"_id" : {
"txnTime" : ISODate("2015-04-27T05:11:54.796Z"),
"msisdn" : "9180877010"
},
"msisdnCount" : 1
},
{
"_id" : {
"txnTime" : ISODate("2015-04-25T18:30:01.111Z"),
"msisdn" : "91808070101"
},
"msisdnCount" : 1
},
{
"_id" : {
"txnTime" : ISODate("2015-04-25T18:30:00.000Z"),
"msisdn" : "91808070101"
},
"msisdnCount" : 2
},
{
"_id" : {
"txnTime" : ISODate("2015-04-27T05:11:54.796Z"),
"msisdn" : "9189877000"
},
"msisdnCount" : 1
},
{
"_id" : {
"txnTime" : ISODate("2015-04-27T05:11:54.796Z"),
"msisdn" : "9189877667"
},
"msisdnCount" : 1
}
],
"ok" : 1
}
-- UPDATE --
To group the documents by date with the format YYYY-MM-DD
, use the Date Aggregation Operators
Example:
var convertedTxnTime = { "$add": [new Date(0), "$txnTime"] };
/*
If using MongoDB 4.0 and newer, use $toDate
var convertedTxnTime = { "$toDate": "$txnTime" };
or $convert
var convertedTxnTime = { "$convert": { "input": "$txnTime", "to": "date" } };
*/
db.campaign_wallet.aggregate([
{ "$match": {
"campaignId" : 1 ,
"txnTime" : {
"$gte" : 1429554600000 ,
"$lte" : 1430159400000
}
} },
{ "$group" : {
"_id" : {
"txnTime_year" : { "$year": convertedTxnTime },
"txnTime_month" : { "$month": convertedTxnTime },
"txnTime_day" : { "$dayOfMonth": convertedTxnTime },
"msisdn": "$msisdn"
},
"msisdnCount" : { "$sum" : 1}
} }
]);
Output:
/* 0 */
{
"result" : [
{
"_id" : {
"txnTime_year" : 2015,
"txnTime_month" : 4,
"txnTime_day" : 25,
"msisdn" : "91808770101"
},
"msisdnCount" : 1
},
{
"_id" : {
"txnTime_year" : 2015,
"txnTime_month" : 4,
"txnTime_day" : 25,
"msisdn" : "91808070101"
},
"msisdnCount" : 3
},
{
"_id" : {
"txnTime_year" : 2015,
"txnTime_month" : 4,
"txnTime_day" : 27,
"msisdn" : "9180877010"
},
"msisdnCount" : 1
},
{
"_id" : {
"txnTime_year" : 2015,
"txnTime_month" : 4,
"txnTime_day" : 27,
"msisdn" : "9189877000"
},
"msisdnCount" : 1
},
{
"_id" : {
"txnTime_year" : 2015,
"txnTime_month" : 4,
"txnTime_day" : 27,
"msisdn" : "9189877667"
},
"msisdnCount" : 1
}
],
"ok" : 1
}
With mongodb 4.0 you can try $toDate
aggregation to convert milliseconds to date format
db.collection.aggregate([
{ "$match": {
"campaignId" : 1 ,
"txnTime" : {
"$gte" : 1429554600000 ,
"$lte" : 1430159400000
}
}},
{ "$project": {
"toDate": {
"$toDate": "$txnTime"
}
}}
])
You can try it here