0

When I run this command:

var news = {
    _id: req.body.newsItemId,
    images: {
        _id: new ObjectId(),
        src: result
    }
}

Shop.findOneAndUpdate({
    _id: ObjectId(req.body.shopId), 
    'news._id':  ObjectId(req.body.newsItemId)},
    {"$set": {
        "news.$": news
    }
}).exec(function(err, shop){
    console.log(err, shop);

})

The non existing field from the news object are overwritten with empty values, so they are removed from the document.

news is a subdocument from shops. So a document looks like:

name: 'test shop',
email: 'email@shop',
products: [],
news: [
    {
       name: 'test news',
       content: 'lorum ipsum....',
       summary: 'lorum',
       images: [
          {
             src: 'news/image_1.jpg',
          }
       ]
    }
]

After running the command above the news contains only a id and 1 image. I want only to overwrite the images array and leave the other properties alone. I have tried it with only images in the set, but then I get this error Mongoose update 'cannot use the part (..) to traverse the element , that is where the $ comes from.

NVO
  • 2,566
  • 5
  • 27
  • 57
  • 3
    Well `'news.$': news` is basically going to overwrite the entire matched object because that's what you are telling it to do. You can always do something like `$set: { 'news.$.content': newContent }` which just updates that element only. Nesting arrays is really not a wise idea, and really is not even supported for updates until MongoDB 3.6 and still is a real pain to query. As such it's not clear if you intend to "update" an entry in the inner "images" array or "append" a new entry to the inner array. The latter is simple. The former is not presently possible, without hardcoded indexes. – Neil Lunn Oct 12 '17 at 10:02
  • Thanks. Actually it was simple. Changed the $set to: `news.$.images` and the variable to `[{src: 'image.jpg'}]` – NVO Oct 13 '17 at 07:04

1 Answers1

0

Solved this by changing the code to this:

var images = [{
    src: result
}]


Shop.findOneAndUpdate({
    _id: ObjectId(req.body.shopId), 
    'news._id':  ObjectId(req.body.newsItemId)},
    {"$set": {
        "news.$.images" : images 
    }
    }).exec(function(err, shop){
        console.log(err, shop);
        return res.status(200).json({message: 'OK'});
    })

So only the images object is overwritten now, and that is what I want.

NVO
  • 2,566
  • 5
  • 27
  • 57