-1

I want to find correct subdocument and change a specific field.

Here are my attempts:

  Book.findOneAndUpdate(
        { _id: req.params.id, chapters: { $elemMatch: { _id: req.params.subid } } },
        { $set: { chapters: { title: 'new title' } } }, { 'new': true }).exec();
    });

Also tried:

  Book.findOneAndUpdate(
    { _id: req.params.id, 'chapters._id': req.params.subid },
    { $set: { 'title': 'new title' } }, { 'upsert': true }).exec();

The first solution removes everything by overwriting it all with a single field, title.

How can I update it correctly?

EDIT:

//Book
    {
        "_id": {
            "$oid": "5ae2f417fe46cf86900af82f"
        },
        "chapters": [
            {                 
                "_id": {
                    "$oid": "5af1b798be6bb05e4427ee65"
                },
               "title": "old title",
               "something": "something"
            },
            //..some more
        ]
    }
ipid
  • 253
  • 1
  • 4
  • 16
  • Can you give us an example of what a `Book` item looks like? – Explosion Pills May 11 '18 at 19:16
  • What is this the problem with the second solution? – Almaju May 11 '18 at 19:22
  • @ExplosionPills Just added an example of the `Book`, check the question. – ipid May 11 '18 at 19:27
  • @Almaju Woah, actually nothing was wrong with it. It take a bit time to fully update it since im forEach:ing it, so when the page was loaded, I didn't see the new result as I assume it was not finished. But after refreshing it again, I did see the change. Thanks for the comment, I wouldn't notice it then. Btw, I recall reading something about async/wait or something. Will that solve the this minor issue to make it wait to load til its fully done? – ipid May 11 '18 at 19:39
  • @ipid yes possibly you can ask another question for that – Explosion Pills May 11 '18 at 19:42

2 Answers2

6

Something like:

const ObjectID = require('mongodb').ObjectID;

var bookId = new ObjectID(req.params.id),
    subId = new ObjectID(req.params.subid);

Book.findOneAndUpdate(
  { _id: bookId, chapters: { $elemMatch: { _id: subId } } },
  { $set: { chapters: { title: 'new title' } } }, { 'new': true }).exec();
});
1

think you need to use positional operator $ info

Book.findOneAndUpdate(
    { _id: req.params.id, 'chapters._id': req.params.subid },
    { $set: 'chapters.$': { 'title': 'new title' } }).exec();

OR to update only title

Book.findOneAndUpdate(
    { _id: req.params.id, 'chapters._id': req.params.subid },
    { $set: 'chapters.$.title': 'new title'}).exec();
  • it should be `Book.findOneAndUpdate( { _id: req.params.id, 'chapters._id': req.params.subid }, { $set: {'chapters.$': { 'title': 'new title' } }}).exec();` – Xiaoyu Xu Mar 17 '20 at 11:24