简体   繁体   中英

mongoose findOneAndUpdate deletes nested vars

In my express/mongoose code when I update a nested var it deletes any other nested vars in the object I didn't update?

My schema:

var MySchema = new Schema({
  active: { type: Boolean, required: true, default: true },
  myvar: {
    useDefault: { type: Boolean, required: true },
    custom: { type: String },
    default: { type: String }
  }
});

My express middleware update function:

var updateData = req.body;
MySchema.findOneAndUpdate({ active: true }, updateData, function(err, myschema) {
    if (err) throw err;
    if (!myschema) { response(403, { success:false, message: "myschema not updated." }, res); }
    // success
    response(200, { success:true, message: "myschema updated." }, res);
});

The record initially look like this:

{
    "myvar": {
        "useDefault": true,
        "custom": "some custom var",
        "default": "some value"
    }
}

When I submit an update to say the myvar.useDefault value the record ends up like this:

{
    "myvar": {
        "useDefault": false
    }
}

Can anyone advise how to update only the targeted var and leave any other vars as they were?

The answer was to convert the response.body object to dot notation and pass that modified object to mongoose findOneAndUpdate. Thanks to @btkostner on Gitter for the answer and his toDot function. Here is the relevant bits of code:

function(req, res) {
  // convert response to dot notation so objects retain other values
  var dotData = toDot(req.body, '.');
  MySchema.findOneAndUpdate({ active: true }, dotData, function(err, myschema) {
    ...
}

// author: @btcostner 
function toDot (obj, div, pre) {
  if (typeof obj !== 'object') {
    throw new Error('toDot requires a valid object');
  }
  if (pre != null) {
    pre = pre + div;
  } else {
    pre = '';
  }
  var iteration = {};
  Object.keys(obj).forEach(function(key) {
    if (_.isPlainObject(obj[key])) {
      Object.assign(iteration, _this.toDot(obj[key], div, pre + key));
    } else {
      iteration[pre + key] = obj[key];
    }
  });
  return iteration;
};

NOTE: I had to convert the toDot() function to ES5 for my project, here is the original ES6 version: github.com/elementary/houston/blob/master/src/lib/helpers/dotNotation.js

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