Home > other >  How to push inside nested array of object that have a precise value of a key in MongoDB?
How to push inside nested array of object that have a precise value of a key in MongoDB?

Time:12-06

I have one question about a problem that I'm not able to fix. I try to update push a string passed via Query in my mongoose collection. My collection are like this:

    {
        "_id": {
            "$oid": "6199288597e42bf84d017f9e"
        },
        "name": "Lisa",
        "surname": "Bianchi",
        "ID_school": "afbH598U3",
        "classes": [
            {
                "class": "5A",
                "activities": {
                    "in_progress": [],
                    "finisched": []
                },
                "_id": {
                    "$oid": "6199288597e42bf84d017f9f"
                }
            },
            {
                "class": "1A",
                "activities": {
                    "in_progress": [],
                    "finisched": []
                },
                "_id": {
                    "$oid": "6199288597e42bf84d017fa0"
                }
            }
        ],
        "email": "[email protected]",
        "__v": 0
    }

and I try to push a string in in_progress array that match, for example, with class:"5A" using this way:

    import db from "../models/index.js";
    
    const Teacher = db.teacher
    
    const updateActivity = (req, res) => {
        const query = { _id: req.query.id};
        const update =  {$push:{'classes.$[group].activities.in_progress': req.query.data } };
        const options = {arrayFilters: { 'group.class': req.query.class }};
    
        Teacher.findOneAndUpdate(query, update, options).exec((err, data) => {
            if (err) {
                res.status(400).send({ message: err });
                return;
            } else {
                res.status(200).send(data);
            }
        })
    }
    
    const API = {
        updateActivity
    }
    
    export default API

The query works fine, but nothing was pushed. I tested whit Insomnia passing in the Query field

    id = 6199288597e42bf84d017f9e;
    class:'5A';
    data:"pushed"

Any suggestion? Thanks!

CodePudding user response:

try this way by passing classes.class in query and also change push to $push:{'classes.$.activities.in_progress': req.query.data }

 const updateActivity = (req, res) => {
    const query = { _id: req.query.id ,'classes.class': req.query.class};
    const update =  {$push:{'classes.$.activities.in_progress': req.query.data } };

    Teacher.updateOne(query,update).exec((err, data) => {
        if (err) {
            res.status(400).send({ message: err });
            return;
        } else {
            res.status(200).send(data);
        }
    })
}

CodePudding user response:

There are two ways of doing this:

Option 1: arrayFilters - more flexible Docu

The option you are using. You have a syntax error - arrayFilters should be an array of documents.

const updateActivity = (req, res) => {
  const query = { _id: req.query.id };
  const update = {
    $push:{ 'classes.$[group].activities.in_progress': req.query.data }
  };

  // This MUST be an array of filter documents!
  const options = { arrayFilters: [{ 'group.class': req.query.class }] };
    
  Teacher
    .findOneAndUpdate(query, update, options)
    .exec((err, data) => {
      if (err) {
        res.status(400).send({ message: err });
        return;
      } else {
        res.status(200).send(data);
      }
    });
}

Option 2: Via Query (as answered by @Saurabh Mistry)

Repeating his answer for completeness

By specifying a query that targets a particular element in an array within result documents.

const updateActivity = (req, res) => {
  const query = {
    _id: req.query.id,
    'classes.class': req.query.data,
  };
  const update = {
    $push:{ 'classes.$.activities.in_progress': req.query.data }
  };

  Teacher
    .findOneAndUpdate(query, update, options)
    .exec((err, data) => {
      if (err) {
        res.status(400).send({ message: err });
        return;
      } else {
        res.status(200).send(data);
      }
    });
}

  • Related