28

I have searched many questions on nested objects, but all I found where related to array[s].

I am looking for a updating simple nested object in mongoose.

From here http://mongoosejs.com/docs/guide.html

there is an example schema :
var blogSchema = new Schema({
  title:  String,
  author: String,
  body:   String,
  comments: [{ body: String, date: Date }],
  date: { type: Date, default: Date.now },
  hidden: Boolean,
  meta: {
    votes: Number,
    favs:  Number
  }
});

Once created a document,

How can I change the favs number later on?

There is no document for the same that I could find.

This is what I did:

blog.findById(entityId, function(err, mainDoc){
      if(err || !mainDoc) return next(err || 'Document not found');
      var subDoc = mainDoc['meta'];
      if(subDoc){
        subDoc = _.extend(subDoc, { favs : 56 }); //_ lib already available
        console.log(mainDoc.get('meta')); //Prints the updated result with favs = 56  OK
        mainDoc.save(function(err, doc){
           console.log(doc.get('meta')); // prints the updated results with favs = 56 OK
        });
      } else next('Not found');
    });

Everything works file and all console gives the desired result.

But when I switch to mongoose console and query the document, I do not get the updated result.

I know there can be other ways to achieve the same, but I am only looking for what I am doing wrong in this particular code.

Why the console, after saving document, gives unmatched data from database?

Upon enabling the mongoose debug option, I found the in query there is no such data to be updated. Query fires with blank $set. { $set : {} }

Steve P
  • 162
  • 1
  • 11
codeofnode
  • 18,169
  • 29
  • 85
  • 142

3 Answers3

53

If you just want to change the value of favs, you can use a simpler query:

blog.findByIdAndUpdate(entityId, {$set: {'meta.favs': 56}}, function(err, doc) {
    console.log(doc);
});
Gergo Erdosi
  • 40,904
  • 21
  • 118
  • 94
  • 3
    I know well this is better answer. but i was actually looking to find what i am doing wrong in my above code. – codeofnode May 23 '14 at 15:33
  • 1
    If 'favs' is a variable. Then How can I achieve something like below? blog.findByIdAndUpdate(entityId, {$set: {'meta[favs]': 56}}, function(err, doc) { console.log(doc); }); – Rajdeep Gautam Feb 10 '18 at 19:30
  • @RajdeepGautam if the key is variable then you will do like var key = 'meta.' + favs; and now blog.findByIdAndUpdate(entityId, {$set: {[key]: 56}}, function(err, doc) { console.log(doc); }); I also edited answer, if its get approved by peers :) – Asad Ali Choudhry Jul 01 '19 at 10:31
  • you could do something like `\`meta[${favs}]\`` where favs is a variable – Akshay Kumar Jan 18 '22 at 18:38
3

Hope I ain't late and will be able to help someone. This Works with deep nested objects as well. No limitations.

    const updateNestedObjectParser = (nestedUpdateObject) => {
    const final = {

    }
    Object.keys(nestedUpdateObject).forEach(k => {
        if (typeof nestedUpdateObject[k] === 'object' && !Array.isArray(nestedUpdateObject[k])) {
            const res = updateNestedObjectParser(nestedUpdateObject[k])
            Object.keys(res).forEach(a => {
                final[`${k}.${a}`] = res[a]
            })
        }
        else
            final[k] = nestedUpdateObject[k]
    })
    return final
}

    console.log(updateNestedObjectParser({
    a: {
        b: {
            c: 99
        },
        d: {
            i: {
                l: 22
            }
        }
    },
    o: {
        a: 22,
        l: {
            i: "ad"
        }
    }
}))
  • This is actually a really nice & simple parser, for building a generic update function with an object as input. Thanks! – Claes Zacho Aug 09 '23 at 13:35
-1

The problem is that you can't do anything with data from mongoose once you've got it other than sending it to the client.

HOWEVER, there is the lean method that makes it so you can then update the info and do whatever you want with it.

That would look like this:

blog.findById(entityId).lean().exec(function (err, mainDoc) {
    if (err || !mainDoc) {
        return next(err || 'Document not found');
    }
    var subDoc = mainDoc.meta;
    if(subDoc){
        subDoc.favs = 56;
        blog.update({_id: entityId}, mainDoc, function(err, doc){
            console.log(doc.get('meta'));
        });
    } else {
        next('Not found');
    }
});
Brian Noah
  • 2,962
  • 18
  • 27