简体   繁体   中英

MongoDB/Mongoose : CastError in updateMany $inc

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?

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

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);
  }
);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM