xNiceEinz
xNiceEinz

Reputation: 53

Mongoose get array of Date with Values

i wanna enter a startDate and a endDate to my Mongoose Aggregation to get the registered Users foreach day between the range. I know i could user the normal count function but i thinkt its better to use the aggregations for it what do you think?

var startDate = 2016-01-05;
var endDate = 2016-01-07;
history : [
    ['2016-01-05', 23], // Day 1 = 23 Users
    ['2016-01-06', 34], // Day 2 = 34 Users
    ['2016-01-07', 43]  // Day 3 = 43 Users
];

so i'm searching for something like

User.aggregate( [ { "$group": { "created": { $gte: startDate, $lt: endDate } } } ], function (err, users) { history.push(users); } );

Upvotes: 2

Views: 752

Answers (1)

chridam
chridam

Reputation: 103365

Aggregation indeed would be the ideal solution but how it generates the result is different from your expected output, depending on your application needs (I presume most probably you want to use this data to display in a graph).

You could approach this in a couple of ways. Not the best solution since it depends on how your data is structured, i.e. it assumes the created date field in your users collection follows a time series (a users is created per day) and is a proper mongo date, but will at least get you going.

Let's consider the aggregation pipeline first. Since you want to produce a list of user counts for each day within a specified data range, you could construct your pipeline in such a way that after the $match pipeline step, use the $group operator to create as the group key a string representation of the created date field using the $dateToString operator, which can be used to group by a day in the "YYYY-MM-DD" format. Then get the count of each accumulated documents using the $sum operator:

var startDate = new Date("2016-01-05");
var endDate = new Date("2016-01-08");

var pipeline = [
    {
        "$match": {
            "created": {
                "$gte": startDate,
                "$lt": endDate
            }
        }
    },      
    {
        "$group": {
            "_id": {
                "yearMonthDay": { 
                    "$dateToString": { 
                        "format": "%Y-%m-%d", 
                        "date": "$created" 
                    } 
                }
            },
            "count": { "$sum": 1 }
        }
    }
];

You can then run the aggregation pipeline, manipulate the result to get the final array in the desired format:

User.aggregate(pipeline, function (err, users){
    if (err) {/* handle error */ }
    console.log(JSON.stringify(users, null, 4));
    var data = users.map(function (u){  return [u._id.yearMonthDay, u.count]; });
    console.log(JSON.stringify(data, null, 4));
});

Upvotes: 1

Related Questions