mongodb - Counting number of records that where date is in date range? -
i have collection documents below:
{startdate: isodate("2016-01-02t00:00:00z"), enddate: isodate("2016-01-05t00:00:00z")}, {startdate: isodate("2016-01-02t00:00:00z"), enddate: isodate("2016-01-08t00:00:00z")}, {startdate: isodate("2016-01-05t00:00:00z"), enddate: isodate("2016-01-08t00:00:00z")}, {startdate: isodate("2016-01-05t00:00:00z"), enddate: isodate("2016-01-10t00:00:00z")}, {startdate: isodate("2016-01-07t00:00:00z"), enddate: isodate("2016-01-10t00:00:00z")}
i return record every date between minimum startdate
, maximum enddate
. along each of these records return count of number of records startdate
, enddate
contain date.
so above example min startdate
1/2/2016
, max enddate
1/10/2016
return dates between 2 along counts. see desired output below:
{date: isodate("2016-01-02t00:00:00z"), count: 2} {date: isodate("2016-01-03t00:00:00z"), count: 2} {date: isodate("2016-01-04t00:00:00z"), count: 2} {date: isodate("2016-01-05t00:00:00z"), count: 4} {date: isodate("2016-01-06t00:00:00z"), count: 3} {date: isodate("2016-01-07t00:00:00z"), count: 4} {date: isodate("2016-01-08t00:00:00z"), count: 4} {date: isodate("2016-01-09t00:00:00z"), count: 2} {date: isodate("2016-01-010t00:00:00z"), count: 2}
please let me know if doesn't make sense , can try explain in more detail.
i able using loop below:
var startdate = isodate("2016-01-02t00:00:00z") var enddate = isodate("2016-02-10t00:00:00z") while(startdate < enddate){ var counts = db.data.find( { startdate: {$lte: startdate}, enddate: {$gte: startdate} } ).count() print(startdate, counts) startdate.setdate(startdate.getdate() + 1) }
but i'm wondering if there way using aggregation framework? come sql background looping data bad idea. same rule apply mongodb? should concerned using looping here , try use aggregation framework or valid solution?
your best bet here mapreduce. because can loop values in between "startdate" , "enddate" within each document , emit each day ( or other required interval ) between values. matter of accumulating per emitted date key data:
db.collection.mapreduce( function() { for( var d = this.startdate.valueof(); d <= this.enddate.valueof(); d += 1000 * 60 * 60 * 24 ) { emit(new date(d), 1) } }, function(key,values) { return array.sum(values); }, { "out": { "inline": 1 } } )
this produces results this:
{ "results" : [ { "_id" : isodate("2016-01-02t00:00:00z"), "value" : 2 }, { "_id" : isodate("2016-01-03t00:00:00z"), "value" : 2 }, { "_id" : isodate("2016-01-04t00:00:00z"), "value" : 2 }, { "_id" : isodate("2016-01-05t00:00:00z"), "value" : 4 }, { "_id" : isodate("2016-01-06t00:00:00z"), "value" : 3 }, { "_id" : isodate("2016-01-07t00:00:00z"), "value" : 4 }, { "_id" : isodate("2016-01-08t00:00:00z"), "value" : 4 }, { "_id" : isodate("2016-01-09t00:00:00z"), "value" : 2 }, { "_id" : isodate("2016-01-10t00:00:00z"), "value" : 2 } ], "timemillis" : 35, "counts" : { "input" : 5, "emit" : 25, "reduce" : 9, "output" : 9 }, "ok" : 1 }
your dates rounded day in sample, if not in real data simple matter of date math applied in order round per interval.
Comments
Post a Comment