skip to Main Content

My MongoDB schema (simplified):

user: ObjectID
calories: Number
meals:[{
    calories: Number
    name:String
}]

And I have a updateMany query:

await Meals.updateMany(
  { user: user, 'meals.name': extraMealName },
  { $inc: { calories: 'meals.$.calories' } },
  {multi : true},  
  function(error, result) {
    console.log(error);
  }
);

The query throws me this error:

CastError: Cast to Number failed for value "meals.$.calories" at path "calories"

I have tried changing the query for the last hour, but nothing worked… I also browsed stackoverflow, but found nothing I could work with

Does someone have an idea how to fix this?

2

Answers


  1. the $inc has a syntax error, $inc expects a number not string so try some like this.

    await Meals.updateMany(
      { user: user, 'meals.name': extraMealName },
      { $inc: { calories: { $sum: '$meals.$.calories' } } },
      { multi: true },
      function(error, result) {
        console.log(error);
      }
    );
    
    Login or Signup to reply.
  2. Using pipelined update,

    • $reduce, go through the meals array and add up the calories where name=extraMealName
    • $subtract from calories, the sum from previous step

    mongoplayground

    db.Meals.update({
      user: "user", "meals.name": "extraMealName"
    },
    [
      {
        $set: {
          calories: {
            $subtract: [
              "$calories",
              {
                $reduce: {
                  input: "$meals",
                  initialValue: 0,
                  in: {
                    $add: [
                      "$$value",
                      {
                        $cond: [
                          {$eq: ["$$this.name", "extraMealName"]},
                          "$$this.calories",
                          0
                        ]
                      }
                    ]
                  }
                }
              }
            ]
          }
        }
      }
    ]);
    

    Updated for multiple fields.

    db.collection.update({
      user: "user", "meals.name": "extraMealName"
    },
    [
      {
        $addFields: {
          reducedValues: {
            $reduce: {
              input: "$meals",
              initialValue: {
                calories: 0, fat: 0
              },
              in: {
                calories: {
                  $add: [
                    "$$value.calories",
                    {
                      $cond: [
                        {$eq: ["$$this.name", "extraMealName"]},
                        "$$this.calories",
                        0
                      ]
                    }
                  ]
                },
                fat: {
                  $add: [
                    "$$value.fat",
                    {
                      $cond: [
                        {$eq: ["$$this.name", "extraMealName"]},
                        "$$this.fat",
                        0
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      },
      {
        $set: {
          "calories": {
            $subtract: ["$calories", "$reducedValues.calories"]
          },
          "fat": {
            $subtract: ["$fat", "$reducedValues.fat"]
          },
          
        }
      }
    ]);
    

    Playground

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search