kaytrance
kaytrance

Reputation: 2757

Group by date several variables

Using mongodb via mongoose in my node.js project. My documents have the following structure:

{ created: new Date("2014-12-24"), last_visited: new Date("2014-12-24") },
{ created: new Date("2014-12-16"), last_visited: new Date("2014-12-24") },
{ created: new Date("2014-12-13"), last_visited: new Date("2014-12-13") },
{ created: new Date("2014-12-12"), last_visited: new Date("2014-12-20") },
{ created: new Date("2010-01-01"), last_visited: new Date("2014-12-20") }

I want to display how many documents were created/updated at certain date in the last 30 days. So the output should be like:

{ date: ISODate("2014-12-12"), created: 2, last_visited: 0 },
{ date: ISODate("2014-12-13"), created: 1, last_visited: 0 },
{ date: ISODate("2014-12-16"), created: 1, last_visited: 0 },
{ date: ISODate("2014-12-20"), created: 0, last_visited: 2 },
{ date: ISODate("2014-12-22"), created: 0, last_visited: 1 },
{ date: ISODate("2014-12-24"), created: 0, last_visited: 2 },

Notice that year 2010 entry was skipped due to it is older that 30 days.

How can I do that?

Upvotes: 0

Views: 125

Answers (2)

Dineshaws
Dineshaws

Reputation: 2083

Try this

db.users.aggregate([
    {$group: {
            "_id": {
                month: {$month: "$created"},
                day: {$dayOfMonth: "$created"},
                year: {$year: "$created"},
            },
            date: {$max: '$created'},
            created: {$sum: 1},
            last_visited: {$sum: 1},
        }},
        {$sort: {
            'date': -1
        }}
])

Thanks

Upvotes: 1

Disposer
Disposer

Reputation: 6371

A map reduce problem:

var old = new Date();
old.setDate(old.getDate()-30);

var filter = { created : {$gt : old}, last_visited : {$gt : old} };

var map = function()
{        
    emit(this.created, {created : 1, last_visited : 0 });      
    emit(this.last_visited, {created : 0, last_visited : 1 });    
}

var reduce = function(key, values)
{
    var out = {created : 0, last_visited : 0 };

    for(i in values)
    {
        var value  = values[i];
        if(value.created != 0)
        {
            out.created++;
        }
        else
        {
            out.last_visited++;
        }
    }

    return out;
}

db.runCommand(
               {
                 mapReduce: "test2",
                 map: map,
                 reduce: reduce,                
                 out: { "inline": 1 },
                 query: filter
               }
             ).results

Upvotes: 1

Related Questions