简体   繁体   中英

Update value inside mongodb array object

I'm trying to update a value inside my array of objects. Looking at the above mongoDB schema what I want is: Find an expense with the ID match with the _id and need to update the fields with new ones from the req.body. Just need to update the: expensesType, description, price and status.

MongoDB 架构

The following code is what I tried to do. First I need to match the right expense and it works fine but when I try to house.save() show me a message 'house.save is not a function'. So I think maybe I need to use a mongoDB function to get the result.

router.put("/editExpense/:id", ensureAuthenticated, (req, res) => {
  var id = mongoose.Types.ObjectId(req.params.id);
  House.find(
    { "expensesHouse._id": id },
    {
      members: 1,
      name: 1,
      description: 1,
      address: 1,
      type: 1,
      user: 1,
      userID: 1,
      userType: 1,
      expensesHouse: { $elemMatch: { _id: id } },
      date: 1
    }
  ).then(house => {
    console.log(house);
    expenseType = req.body.expenseType;
    description = req.body.description;
    price = req.body.price;
    status = req.body.status;

    house.save().then(() => {
      req.flash("success_msg", "Expenses Updated");
      res.redirect("/houses/dashboard");
    });
  });
});

****** UPDATED ******

After a search I found this updateOne and after adjusts, this is my final result but this way I delete every record..

router.put("/editExpense/:id", ensureAuthenticated, (req, res) => {
  var id = mongoose.Types.ObjectId(req.params.id);
  House.updateOne(
    { "expensesHouse._id": id },
    {
      members: 1,
      name: 1,
      description: 1,
      address: 1,
      type: 1,
      user: 1,
      userID: 1,
      userType: 1,
      expensesHouse: { $elemMatch: { _id: id } },
      date: 1
    },
    { $set: { "expensesHouse.expenseType": req.body.expenseType } }
  ).then(house => {
    req.flash("success_msg", "Expenses Updated");
    res.redirect("/houses/dashboard");
  });
});

*********** RESOLUTION *********** I just fixed the problem the way I show below.

 House.updateOne(
{ "expensesHouse._id": id },
{
  $set: {
    expensesHouse: {
      expenseType: req.body.expenseType,
      description: req.body.description,
      price: req.body.price,
      status: req.body.status
    }
  }
}

You are really close to the answer the problem right now that you are having is syntax difference between find and UpdateOne

This is what Find expects, Check MongoDB docs

db.collection.find(query, projection)

This is what updateOne expects, Check Mongo docs

 db.collection.updateOne(
   <filter>,
   <update>,
   {
     upsert: <boolean>,
     writeConcern: <document>,
     collation: <document>,
     arrayFilters: [ <filterdocument1>, ... ],
     hint:  <document|string>        // Available starting in MongoDB 4.2.1
   }
)

See the Difference? Second parameter should be update not projection because Update one returns

  • matchedCount containing the number of matched documents
  • modifiedCount containing the number of modified documents
  • upsertedId containing the _id for the upserted document.
  • A boolean acknowledged as true if the operation ran with write concern or false if write concern was disabled.

So Your code should be

House.updateOne(
    { "expensesHouse._id": id },
    { $set: { "expensesHouse.expenseType": req.body.expenseType } }
  ).then(house => {
    req.flash("success_msg", "Expenses Updated");
    res.redirect("/houses/dashboard");
  });
});
House.findOneAndUpdate({userId : req.params.userId}, 
    { $set: { "expensesHouse.$[element].status": req.body.status } },
    { multi:true, arrayFilters: [{ "element.userID" : req.params.subUserId }], new:true })

Your Api reuquest consist of both the IDs (outer as well as inner) like /api/update/:userId/:subUserId

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