8

I'm trying to delete a key before sending data back to the browser. For some reason, maybe because it is a mongoose object, this isn't working:

delete myObject.property

If I do console.log(delete myObject.property) I get true which I understand means the property was not deleted. How can I get rid of this key?

(More background: I know I could leave it off by using a mongoose select query, but I do need to select the key initially. I can also set it to null, which works fine, but I'd much rather get rid of the key completely)

Glenn
  • 4,195
  • 9
  • 33
  • 41
  • 1
    usially that means that your try to use `delete` on array. if you did that -> try to use `for-of` loop (`for` for browser) to delete all the same properties into array of elements – Mikita Melnikau Jan 10 '18 at 23:04

6 Answers6

6

As MikaS states, you need to convert to convert the Mongoose document object into an ordinary object first:

const newObj = myObject.toObject();
delete newObj.property;

This should be fine if you're doing this once. However, if you have to repeat this logic everywhere you return this this type of document with certain keys omitted or other transformations, you should define transformations on your schema:

// specify the transform schema option
if (!schema.options.toObject) schema.options.toObject = {};
schema.options.toObject.transform = function (doc, ret, options) {
  // any kind of simple/complicated transformation logic here
  // remove the _id of every document before returning the result
  delete ret._id;
  return ret;
}

// without the transformation in the schema
doc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }

// with the transformation
doc.toObject(); // { name: 'Wreck-it Ralph' }

Read about Document#toObject and transformations in the docs

Govind Rai
  • 14,406
  • 9
  • 72
  • 83
2

Convert the Mongoose document object to an ordinary Javascript object first:

const newObj = myObject.toObject();
delete newObj.property;
Mika Sundland
  • 18,120
  • 16
  • 38
  • 50
0

Will work in some versions:

myObject.set('property_to_delete', undefined, {strict: false} );
myObject.save();
Tomasz Bubała
  • 2,093
  • 1
  • 11
  • 18
0

Use lodash pickby method. Docs: https://lodash.com/docs/#pickBy

Rafael Hovsepyan
  • 781
  • 8
  • 14
0

delete returns true except when the property is non-configurable. So your key is indeed deleted. You still see the key because it is available in the prototype chain when deleted in the Mongoose document instance.

Try a transform instead:

let Schema = new mongoose.Schema({
  myProperty: String,
  myOtherProperty: String
}, {
  toObject: {
    transform: function (doc, ret) {
      delete ret.myOtherProperty;
    }
  },
  toJSON: {
    transform: function (doc, ret) {
      delete ret.myOtherProperty;
    }
  }
});
Juan
  • 6,125
  • 3
  • 30
  • 31
0

I found a solution for myself, where I just create a little helper method on the Schema to remove whatever field it may be.

Example User Schema (simplified):

const UserSchema = new Schema(
  {
    name: {
      type: String,
      required: true,
      trim: true
    },
    email: {
      type: String,
      required: true,
      trim: true,
    },
    password: {
      type: String,
      required: true,
      trim: true
    },
  },
  {
    timestamps: true
  }
);

const User = mongoose.model("User", UserSchema);
module.exports = User;

For a reasons of security, I like removing the password salt from a User object when sending back to client. I might make a helper method in my UserSchema, like:

UserSchema.methods.hidePasswordSalt = function() {
  let self = this;
  self = self.toObject();
  if (self.password) {
    delete self.password;
  }
  return self;
};

Then, in my Controller, etc, when I retrieve my User, I call the method and send the result:

User.findOne({ _id: req.session.userId })
  .then(user => {
    user = user.hidePasswordSalt(); // removes password field
    return res.status(200).json(user);
  })
  .catch(error => {
    return res.status(403).json(error.errors);
  });
twknab
  • 1,741
  • 1
  • 21
  • 35