Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongoose - foreach loop with aggregate result

I'm using node.js with mongoose plugin to build simple application with tasks to do. My mongoDB schema looks like this:

var userSchema = mongoose.Schema({

    username: String,
    email  : String,
    password : String,
    tasks: [{
      title: String,
      description: String,
      date: {type: Array, "default":[]}, 
      currentPeriod: Number,  
      periodQuantity: Number,
      done: Boolean
    }]

});

And what I want to do is to (for example) acquire tasks, which "done" variable is set to true, and are part of one user(same document). At the moment, my query looks like this:

    User.aggregate({$match:{'email':req.user.email}},{$unwind:"$tasks"},{$match:{'tasks.done':true}},{$project:{'tasks':1,'_id':0}}, function(err,tasks){
      if (err) {
        console.log('Something went wrong during getting inactive task(s) for user "' + req.user.email + '": ' + err);
        res.send(err);
      }
      console.log('Succesfully got ' + tasks.length + ' inactive task(s) for user: "' + req.user.email + '".');
      res.json(tasks);
    });

The problem is that result of such query is like this

    [
    {"tasks":{"_id":"57372ef07329d9d8f2921ede","title":"Done1","description":"Done1Desc","currentPeriod":3,"periodQuantity":3,"done":true}},
    {"tasks":{"_id":"57372ef07329d9d8f2921edf","title":"Done2","description":"Done2Desc","currentPeriod":11,"periodQuantity":11,"done":true}},
    {"tasks":{"_id":"57372ef07329d9d8f2921ee3","title":"Done3","description":"Done3Desc","currentPeriod":3,"periodQuantity":3,"done":true}},
    {"tasks":{"_id":"57372ef07329d9d8f2921ee4","title":"Done4","description":"Done4Desc","currentPeriod":4,"periodQuantity":4,"done":true}}
    ]

While I want only values of "property" tasks. I managed to get result that interests me in mongo console using

> var results = [];
> db.users.aggregate({$match:{'email':'admin'}},{$unwind:"$tasks"},{$match:{'tasks.done':true}},{$project:{'tasks':1,'_id':0}}).forEach(function(u) {results.push(u.tasks)})
> results
[
        {
                "_id" : ObjectId("57372ef07329d9d8f2921ede"),
                "title" : "Done1",
                "description" : "Done1Desc",
                "currentPeriod" : 3,
                "periodQuantity" : 3,
                "done" : true
        },
        {
                "_id" : ObjectId("57372ef07329d9d8f2921edf"),
                "title" : "Done2",
                "description" : "Done2Desc",
                "currentPeriod" : 11,
                "periodQuantity" : 11,
                "done" : true
        },
        {
                "_id" : ObjectId("57372ef07329d9d8f2921ee3"),
                "title" : "Done3",
                "description" : "Done3Desc",
                "currentPeriod" : 3,
                "periodQuantity" : 3,
                "done" : true
        },
        {
                "_id" : ObjectId("57372ef07329d9d8f2921ee4"),
                "title" : "Done4",
                "description" : "Done4Desc",
                "currentPeriod" : 4,
                "periodQuantity" : 4,
                "done" : true
        }
]
>

I tried to use foreach and each functions at the end of second's snippet, but when I do so I'm getting an error

TypeError: User.aggregate(...).forEach is not a function
like image 621
Nevaan Avatar asked Dec 06 '25 07:12

Nevaan


1 Answers

This can be done inside the aggregate query using $group. Check the query below:

db.users.aggregate.aggregate([{
    $unwind: '$tasks'
}, {
    $match: {
        email: req.user.email,
        'tasks.done': true
    }
}, {
    $group: {
        _id: null,
        tasks: {
            $push: '$tasks'
        }
    }
}]);
like image 146
Thomas Bormans Avatar answered Dec 07 '25 23:12

Thomas Bormans