简体   繁体   中英

mongoose findOneAndUpdate appends objects only

I have an object like follows;

var exObj = { 'title' : 'name1'};

some of them have a data property of objects (not an array as I want to reference by name) and look like

  exObj = {
    title : 'name2',
    data : {
      prop1 : 'prop1',
      prop2 : 'prop2'
    }
  }

Now I want to add another property to data, sometimes the data property will exist, and sometimes not, but I want to append a property (addedProp) and save it so I will end up with this;

 exObj = {
    title : 'name2',
    data : {
      prop1 : 'prop1',
      prop2 : 'prop2',
      addedProp : 'value'
    }
  }

When using findOneAndUpdate I can only seem to pass in a whole object which is then appended; something like this is what I currently do.

var data = {};
data.addedProp = value;

Collection.findOneAndUpdate({
  title: 'name2'
}, {
  data
}, {
  upsert: true
})
.exec(function(err) {
  if (err) {
    console.log(err);
  } else {
    console.log('Updated');
  }
});

But obviously this overides the data object that exists; what is the correct way to do a findOneAndUpdate and make more meaningful changes to the object? I tried casting to toObject() but then I don't have a proper mongoose object to do a .save() on.

To add further clarification; which this worked for simple properties (and worked well) which I know are set; there are some values I wish to add which I need to check if they have a value for the property before adding the property .

So something like this;

    Collection.findOneAndUpdate({
      field: val
      }, {
      if (tObj.title) {
        title = tObj.title;
      }

      if (tObj.date) {
        release_date = tObj.date;
      }

      if (tObj.name) {
        name = tObj.name;
      }
    }, { upsert: true
    })
    .exec(function(err) {
    if (err) {
     //handler
    } else {
    //handler
    }
  });

Your question first seem daunting, but solution is quite simple, you don't need to use $ or upsert, because you are not using any array , so don't need of positional operator or upsert. You can use below code.

Collection.findOneAndUpdate({
  title: 'name2'
},{
    $set:{"data.prop3":"new prop3"}
})
.exec(function(err) {
  if (err) {
    console.log(err);
  } else {
    console.log('Updated');
  }
});

It will add prop3 if not exists, or if it exists it will update it. I have checked the code on my local db with update and findOneAndUpdate

You need to use dot notation to target specific fields within an embedded object, building up your update object based on the supplied fields:

var update = {};
if (tObj.title) {
    update.title = tObj.title;
}
if (tObj.data) {
    if (tObj.data.prop1) {
        update['data.prop1'] = tObj.data.prop1;
    }
    if (tObj.data.prop2) {
        update['data.prop2'] = tObj.data.prop2;
    }
    if (tObj.data.addedProp) {
        update['data.addedProp'] = tObj.data.addedProp;
    }
}

Collection.findOneAndUpdate({
  title: 'name2'
}, {
  $set: update
}, {
  upsert: true
})
.exec(function(err) {

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM