2

How to Update Multiple Objects by Its ID inside an array? I wanted to Update the experience by its ID by the User,

Below i have attached my mongodb json object screenshot:

Image

I can already Create an Experience by the User:

router.put('/experience',
    [
        auth,
        [
            check('title', 'Title is required').not().isEmpty(),
            check('company', 'Company is required').not().isEmpty(),
            check('from', 'From date is required').not().isEmpty(),
        ],
    ],
    async (req, res) => {
        const errors = validationResult(req);
        if (!errors.isEmpty()) {
            return res.status(400).json({ errors: errors.array() });
        }

        const {
            title,
            company,
            location,
            from,
            to,
            current,
            description,
        } = req.body;

        const newExp = {
            title,
            company,
            location,
            from,
            to,
            current,
            description,
        };

        try {
            const profile = await Profile.findOne({ user: req.user.id });
            // unshift is same with push it pushes it in the beginner rather than the end
            profile.experience.unshift(newExp);

            await profile.save();

            res.json(profile);
            console.log(req.body);
        } catch (err) {
            console.error(err.message);
            res.status(500).send('Send Error');
        }
    }
);

and Here is my non working code about the Update strong text

router.patch('/experience/:exp_id', auth, async (req, res) => {
    let id = req.params.exp_id;
    let expId = req.body;
    try {
        const profile = await Profile.findOne({ user: req.user.id });

        profile.experience.findOneAndUpdate(
            { id },
            { $set: { expId } },
            { new: true }
        );
        res.json(profile);
    } catch (err) {
        console.error(err.message);
        res.status(500).send(err.message);
    }
});
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Grizzly Bear
  • 318
  • 4
  • 18
  • use `id` instead of `{id}` and use `{ $set:{ 'expId': expId,,,,,,,more fields if needed} }` instead of `{ $set: { expId } }` in your `findOneAndUpdate` function. – turivishal Jun 05 '20 at 09:56
  • it returns profile.experience.findOneAndUpdate is not a function my profile.experience is an array of objects btw. user: { // Special field type because // it will be associated to different user type: mongoose.Schema.Types.ObjectId, ref: 'user', }, experience: [ { title: { type: String, required: true, }, company: { type: String, required: true, }, location: { type: String, }, from: { type: Date, required: true, }, – Grizzly Bear Jun 07 '20 at 06:42

2 Answers2

1

Look around this, corrected below things:

  1. from { id } to { "experience._id": id }
  2. { $set: { expId } } to { $set: { fields of experience } }
  3. removed const profile = await Profile.findOne({ user: req.user.id });
  4. from profile.experience.findOneAndUpdate to Profile.findOneAndUpdate
  5. added data and error response function (err, data)
router.patch('/experience/:exp_id', auth, async (req, res) => {
    let id = req.params.exp_id;
    let expId = req.body;
    try {
        await Profile.findOneAndUpdate(
            { 
                "experience._id": id
            },
            { 
                $set: { 
                    'experience.$.title': req.body.title, 
                    'experience.$.company': req.body.company, 
                    'experience.$.from': req.body.from, 
                }
            },
            { new: true },
            (err, data) => {
                if (!err){
                    res.json(data);
                }else{
                    res.json(err);
                }
            }
        );
    } catch (err) {
        console.error(err.message);
        res.status(500).send(err.message);
    }
});

Hope this will help you.

turivishal
  • 34,368
  • 7
  • 36
  • 59
-1

https://stackoverflow.com/a/47762417/13199635 This should help you out. Also in your current code, where you are updating your profile.experience, you should probably use {_id: id} instead of just {id}. so your updated code would be like

profile.experience.findOneAndUpdate(
            { _id: id },
            { $set: { expId } },
            { new: true }
        );
        res.json(profile);

Hope this helps

lanxion
  • 1,350
  • 1
  • 7
  • 20
  • It should be `{_id: id}` not `{id: id}`. – turivishal Jun 05 '20 at 09:58
  • Yeah. I assumed he had his own defined id field. – lanxion Jun 05 '20 at 11:06
  • it returns profile.experience.findOneAndUpdate is not a function. How can I fix this? – Grizzly Bear Jun 07 '20 at 06:45
  • @JmMacatangay, Just use `Profile.findOneAndUpdate` – turivishal Jun 07 '20 at 06:48
  • It returns the date but it doesn't update it. In my mongodb atlas the experience has it's own id. I already done the delete one and here's my code: router.delete('/experience/:exp_id', auth, async (req, res) => { try { const profile = await Profile.findOne({ user: req.user.id }); // Get removed index const removeIndex = profile.experience .map((item) => item.id) .indexOf(req.params.exp_id); profile.experience.splice(removeIndex, 1); await profile.save(); res.json(profile); } catch (err) { console.error(err.message); res.status(500).send('Send Error'); } }); – Grizzly Bear Jun 07 '20 at 06:58
  • @turivishal https://stackoverflow.com/q/62791188/11243223 – Grizzly Bear Jul 08 '20 at 09:02
  • @turivishal https://stackoverflow.com/q/64061393/11243223 can you help me agian? – Grizzly Bear Sep 25 '20 at 10:28