1

I had used the reduce function within my local hosted development, however now i have deployed the code to a live server and im now getting an error:

MongoError: exception: invalid operator '$reduce'

Im using it to get daily food diaries to calculate to total calories consumed:

user_food.aggregate({$match:{user_id:mongoose.Types.ObjectId(req.session.user_id)}},{$project: {date:1,calories:{$add:[
                        {$reduce: {input: "$breakfast",initialValue: 0,in: { $add : ["$$value", "$$this.calories"]}}}, 
                        {$reduce: {input: "$lunch",initialValue: 0,in: { $add : ["$$value", "$$this.calories"]}}},
                        {$reduce: {input: "$snacks",initialValue: 0,in: { $add : ["$$value", "$$this.calories"]}}},
                        {$reduce: {input: "$dinner",initialValue: 0,in: { $add : ["$$value", "$$this.calories"]}}}]}}}, function (err, results) {
        //if there is an error
        if (err) {
            console.log("something went wrong: " + err);
            return res.status(500).send(err);
        } else {
            return res.status(200).send(results);
        }
    });

The document for the user food is pretty simple:

{
 "_id": ObjectId("58d26c3dd60bd36f40fa0498"),
 "user_id": ObjectId("587cd30bd338b90a6c18e58f"),
 "calories": 2000,
 "date": 20170222,
 "snacks": [
  {
  "nutrients": {
    "protein": 7.5,
    "carbs": 56.5,
    "fat": 10.5
  },
  "servings": 23.8,
  "calories": 526,
  "name": "Dairy milk"
}
],
 "dinner": [ ],
 "lunch": [
{
  "nutrients": {
    "protein": 9.5,
    "carbs": 25.4,
    "fat": 17.2
  },
  "servings": 60,
  "calories": 751,
  "name": "2 pork sausages rolls"
}
 ],
 "breakfast": [
{
  "nutrients": {
    "protein": "4.8",
    "carbs": "65",
    "fat": "26"
  },
  "servings": 20.5,
  "calories": 438,
  "name": "Oreo"
}
],
"__v": 0
}

If anyone can point me in the right direction to fix this id be very grateful.

Neil Lunn
  • 148,042
  • 36
  • 346
  • 317
William.Doyle
  • 79
  • 1
  • 10

1 Answers1

2

You can try the below aggregation in the 2.6 mongo version.

The $project with $size to replace all the empty arrays with { calories: 0 } followed by $unwind for all embedded arrays and $group on $date and $add all calories.

user_food.aggregate(
 {$project:
     {
      date:1, 
      breakfast :{ $cond: [{$eq: [{$size: "$breakfast"}, 0] }, [ { calories: 0 } ], "$breakfast"] },
      lunch :{ $cond: [{$eq: [{$size: "$lunch"}, 0] }, [ { calories: 0 } ], "$lunch"] },
      snacks :{ $cond: [{$eq: [{$size: "$snacks"}, 0] }, [ { calories: 0 } ], "$snacks"] },
      dinner :{ $cond: [{$eq: [{$size: "$dinner"}, 0] }, [ { calories: 0 } ], "$dinner"] }
     }
 },
 {$unwind:"$breakfast"}, 
 {$unwind:"$lunch"}, 
 {$unwind:"$snacks"}, 
 {$unwind:"$dinner"},
 {$group:{_id:"$date", calories:{$sum:{ $add: [ "$breakfast.calories", "$lunch.calories","$snacks.calories", "$dinner.calories"] }}
 }}
)

For more information on $project part $unwind empty array

Community
  • 1
  • 1
s7vr
  • 73,656
  • 11
  • 106
  • 127