简体   繁体   中英

How to update an object inside a Mongo Document Array (at a specific index)

I want to let a user check off whether they've "acquired" a grocery item and update the Database.

In more concrete terms, when a user checks a box, I want to toggle a Boolean property acquired on an ingredient object. Ingredients are stored in an array on the GroceryList document:

Here is the Schema for a Grocery List

const GroceryListSchema = mongoose.Schema({
  createdAt         : { type: Date, default: Date.now },
  updatedAt         : { type: Date },
  ingredients       : { type: Array },
  recipes           : { type: Array },
  user              : { type: mongoose.Schema.Types.ObjectId, ref: 'UserSchema', required: true },
}

An ingredient looks like this:

{ quantity: '3',
  unit: null,
  ingredient: 'zucchinis, chopped',
  minQty: '3',
  maxQty: '3',
  acquired: false }

I've looked at a lot of similar questions, the Mongoose documentation and the MongoDB documentation and I've tried a ton of different versions but I'm stumped.

Frontend:

function toggleIngredient(elmt, groceryListId, ingrIdx) {
  $.post('/cart/grocery-list/toggleIngredient', {
    groceryListId,
    ingrIdx,
    newValue: elmt.checked, // if checkbox was checked before toggling it
  })
    .then((res) => {
      console.log(res);
    })
    .catch((err) => {
      console.log(err);
    });
}

Backend:

  app.post('/cart/grocery-list/toggleIngredient', (req, res, next) => {
    const { groceryListId, ingrIdx, newValue } = req.body;

    GroceryListSchema.findById(groceryListId, (err, groceryList) => {
      if (err) return next(err);

      // if was unchecked, change to checked & vice-versa
      groceryList.ingredients[ingrIdx].acquired = newValue;

      // save updated grocery list
      groceryList.save().then((updatedList) => {
        console.log(updatedList.ingredients);
      }).catch(error => next(error));
    });
  });

RESULTS / THE PROBLEM: When I run the code above, I successfully see 1 ingredient's acquired property get toggled from false -> true in the callback

console.log(updatedList.ingredients);

However, the next time I fetch the grocery list, that same ingredient's acquired = false . This leads me to believe that the GroceryList document isn't actually getting updated in the database. How do I fix this?

mongoose can't track changes inside the array if you modify array element directly using its index

try adding this line before saving

groceryList.markModified(`ingredients.${ingrIdx}.acquired`);

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