简体   繁体   中英

How to update object inside array inside object?

I have the following Mongooose schema:

    {
      _id: {
        type: String,
        required: true
      },          
      semesters: [
        {
          _id: {
            type: String,
            required: true
          },
          grades: [
            {
              subject: String,
              literalGrade: String,
              grade: Number,
              credits: Number
            }
          ]
        }
      ]
    }

I want to be able to update one grade that is inside semester's grades object using its id. I tried using MongoDb new multiple positional operator to no avail.

This is my current snippet:

User.findOneAndUpdate(
    {
      _id: req.params.user_id,
      "semesters._id": req.params.semester_id
    },
    {
      $set: {
        "semesters.$[x].grades.$[y].subject": req.body.grades.subject,
        "semesters.$[x].grades.$[y].literalGrade": req.body.grades.literalGrade,
        "semesters.$[x].grades.$[y].grade": req.body.grades.grade,
        "semesters.$[x].grades.$[y].credits": req.body.grades.credits
      }
    },
    {
      arrayFilters: [
        { "x._id": req.params.semester_id },
        { "y._id": req.params.grade_id }
      ]
    },
    (err, user) => {
      if (err) return res.json(err);
      res.send({
        message: "Updated grade",
        data: user
      });
    }
  );

Couldn't get any results with the MongoDb positional operator, but found a way to programmatically do it with the help of Naing Lin Aung's answer . Here is the solution:

User.findOne(
    {
      _id: req.params.user_id,
      "semesters.grades._id": req.params.grade_id
    },
    { "semesters.$.grades": 1 },
    (err, user) => {
      if (err) return res.json(err);

      let grades = user.semesters[0].grades;
      let index = null;

      for (let t in grades) {
        if (grades[t]._id == req.params.grade_id) {
          index = t;
          break;
        }
      }

      let grade = grades[index];

      grade.subject = req.body.grades.subject;
      grade.literalGrade = req.body.grades.literalGrade;
      grade.grade = req.body.grades.grade;
      grade.credits = req.body.grades.credits;

      user.save(function(err) {
        if (err) return res.json(err);
        res.json({
          message: "Updated grade",
          data: user
        });
      });
    }
  );

You can take advantage of $[] syntax with arrayFilters

refer this link : https://docs.mongodb.com/manual/reference/operator/update/positional-all

 db.col.update(
{  _id: req.params.user_id }, 
{ $set: { "semesters.$[cond1].grades.$[cond2].subject": req.body.grades.subject } }, 
{ arrayFilters: [ { "cond1._id": req.params.semester_id }, { "cond2._id": req.params.grade_id  } ]  })

You can similarly update other fields in $set

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