I have a collection of ProductViews
.
ProductView
{
productId: \'5b8c0f3204a10228b00a1745,
createdAt: \'2018-09-
Your question is similar to post from 2014.
All the answers provided at that post are valid and it would be much simpler if you can generate missing days in your application code.
Since you have asked for mongodb solution and lot has changed from 2014 I created a new aggregation pipeline that you can use with 3.6 version.
ProductView.aggregate([
-- convert the string date into date type for date calcualtions. can avoid this step if you can store the date as date type in collection
{"$addFields":{"createdAt":{"$dateFromString":{"dateString":"$createdAt"}}}},
-- strip the time part so we can add whole milliseconds from epoch to calculate next day
{"$project":{
"day":{"$dateFromParts":{"year":{"$year":"$createdAt"},"month":{"$month":"$createdAt"},"day":{"$dayOfMonth":"$createdAt"}}}
}},
-- generate two sets of data, one that has count by day, other that has unique days, min day and max day
{"$facet":{
"daycounts":[{"$group":{"_id":"$day","count":{"$sum":1}}}],
"maxmindays":[
{"$group":{
"_id":null,
"days":{"$addToSet":"$day"},
"minday":{"$min":{"$divide":[{"$subtract":["$day",new Date("1-1-1970")]},1000]}},
"maxday":{"$max":{"$divide":[{"$subtract":["$day",new Date("1-1-1970")]},1000]}}
}}
]
}},
{"$project":{
"data":{
"$let":{
"vars":{"maxminday":{"$arrayElemAt":["$maxmindays",0]}},
"in":{
-- $range - iterate from min date to max date one day at a time
"$map":{
"input":{"$range":["$$maxminday.minday",{"$add": ["$$maxminday.maxday", 60*60*24]},60*60*24]},
"as":"r",
"in": {
-- convert back to milliseconds to get the day
"$let":{
"vars":{"current":{"$add": [new Date(0), {"$multiply":["$$r", 1000 ]}]}},
"in":{
-- check if the day is in the collection, if yes lookup view inside the daycount facet to get the matching count, else set the view to zero
"$cond":[
{"$in":["$$current","$$maxminday.days"]},
{
"date":{"$substr":["$$current",0,10]},
"views":{"$let":{"vars":{"daycount":{"$arrayElemAt":["$daycounts",{"$indexOfArray":["$daycounts._id","$$current"]}]}},"in":"$$daycount.count"}}
},
{"date":{"$substr":["$$current",0,10]},"views":0}
]
}
}
}
}
}
}
}
}},
-- flatten the array of data
{"$unwind":"$data"},
-- promote the data to top
{"$replaceRoot":{newRoot:"$data"}}
])