From 632726fe0273ad507138ae9c30a8a890659e8a0f Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Wed, 24 Sep 2014 19:35:00 -0600 Subject: [PATCH] perf(challenges): WIP --- src/controllers/challenges.js | 57 +++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/src/controllers/challenges.js b/src/controllers/challenges.js index 9d2fb5992c..9d5869a7be 100644 --- a/src/controllers/challenges.js +++ b/src/controllers/challenges.js @@ -105,23 +105,48 @@ api.csv = function(req, res, next) { } api.getMember = function(req, res, next) { - var cid = req.params.cid, uid = req.params.uid; - User.findById(uid) - .select('profile.name habits dailys todos rewards') - .exec(function(err, member){ - if(err) return next(err); + var cid = req.params.cid; + var uid = req.params.uid; + + // See http://stackoverflow.com/a/18546277/362790 + // However, this doesn't work. If not all $match conditions are met (eg, if a challenge doesn't have any one of habit/daily/todo/reward + // then the $match fails and that user object is removed from the results. See http://stackoverflow.com/questions/23636175/filter-subdocument-array-while-still-returning-parent-data-if-empty +// User.aggregate() +// .match({_id: uid}) +// .unwind('habits').match({'habits.challenge.id': cid}) +// .unwind('dailys').match({'dailys.challenge.id': cid}) +// .unwind('todos').match({'todos.challenge.id': cid}) +// .unwind('rewards').match({'rewards.challenge.id': cid}) +// .group({_id:'$_id', 'profile.name':'$profile.name', habits:{$push: '$habits'}, dailys:{$push:'$dailys'}, todos:{$push:'$todos'}, rewards:{$push:'$rewards'}}) +// .exec(function(err, member){ +// if (err) return next(err); +// if (!member) return res.json(404, {err: 'Member '+uid+' for challenge '+cid+' not found'}); +// res.json(member[0]); +// }); + + //http://stackoverflow.com/questions/24027213/how-to-match-multiple-array-elements-without-using-unwind + var proj = {'profile.name':'$profile.name'}; + _.each(['habits','dailys','todos','rewards'], function(type){ + proj[type] = { + $setDifference: [{ + $map: { + input: '$'+type, + as: "el", + in: { + $cond: [{$eq: ["$$el.challenge.id", cid]}, '$$el', false] + } + } + }, [false]] + } + }); + User.aggregate() + .match({_id: uid}) + .project(proj) + .exec(function(err, member){ + if (err) return next(err); if (!member) return res.json(404, {err: 'Member '+uid+' for challenge '+cid+' not found'}); - - // Prune un-related tasks. See http://goo.gl/9fnwei - // See http://stackoverflow.com/a/18546277/362790 for fix - _.each(['habits','dailys','todos', 'rewards'], function(type){ - member[type] = _.filter(member[type], function(task){ - return task.challenge && task.challenge.id && task.challenge.id == cid; - }); - }); - - res.json(member); - }) + res.json(member[0]); + }); } // CREATE