Delete a key from a MongoDB document using Mongoose
Asked Answered
S

10

162

I'm using the Mongoose Library for accessing MongoDB with node.js

Is there a way to remove a key from a document? i.e. not just set the value to null, but remove it?

User.findOne({}, function(err, user){
  //correctly sets the key to null... but it's still present in the document
  user.key_to_delete = null;

  // doesn't seem to have any effect
  delete user.key_to_delete;

  user.save();
});
Sihonn answered 20/12, 2010 at 4:42 Comment(2)
I thought I had found it, but after some tests: probably not. This has some good discussion on the topic though. groups.google.com/group/mongoose-orm/browse_thread/thread/…Audrit
LOL nevermind, I guess this was your post!Audrit
S
246

In early versions, you would have needed to drop down the node-mongodb-native driver. Each model has a collection object that contains all the methods that node-mongodb-native offers. So you can do the action in question by this:

User.collection.update({_id: user._id}, {$unset: {field: 1 }});

Since version 2.0 you can do:

User.update({_id: user._id}, {$unset: {field: 1 }}, callback);

And since version 2.4, if you have an instance of a model already you can do:

doc.field = undefined;
doc.save(callback);
Silver answered 4/8, 2011 at 9:6 Comment(12)
This has been fixed in Mongoose 2.X, so you can leave the collection out.Silver
What's the fix? How does one do it. I've read the docs I have.Darg
Either use User.update({ _id: id }, { $unset: { field: 1 }}, callback) or if you have a document instance, set the path to undefined and then save it: doc.field = undefined; doc.save()Alternant
Just a note that if you're trying to remove an old property that's no longer defined in your schema you need to do doc.set('field', undefined)Shedevil
what about deleting doc.field.foo ?Dermot
Will it work if this key is an object? I.e embedded doc, or am i need to set each property of this object to undefined individualy?Welsh
@Dermot delete has no effect in v 4.0.2. I guess it makes sense that you wouldn't be allowed to remove properties from a model but seems like it should just have the same effect as setting to undefined.Corcovado
@Shedevil doc.set('field', undefined) might not be enough since strict mode (default) does not allow to set fields which are not in the schema anymore. doc.set('field', undefined, { strict: false }) worked fine.Hodometer
@AlexanderLink I tried strict: false as you posted, Keystone recorded that the update was performed but the field is still there...Phyle
@AlexanderLink where are you doing the doc.set? Thanks.Riot
Thank you @AlexanderLink I've spent 2 hours looking for this. you are a hero!Kabuki
none of the other comments work. it should be something like this: User.updateOne({ _id: user._id }, { $unset: { field: 1 }}, { strict: false }).Ful
C
74

You'll want to do this:

User.findOne({}, function(err, user){
  user.key_to_delete = undefined;
  user.save();
});
Chickadee answered 9/5, 2011 at 2:52 Comment(2)
That will just set it to null - not what the OP is asking for.Ethylene
As of version 2.4.0 setting a document key to undefined will pass the $unset to mongodb aaronheckmann.posterous.com/mongoose-240Mev
M
53

I use mongoose and using any of the above functions did me the requirement. The function compiles error free but the field would still remain.

user.set('key_to_delete', undefined, {strict: false} );

did the trick for me.

Mahratta answered 28/9, 2016 at 11:30 Comment(4)
Upvoting this useful answer, too bad @alexander-link didn't make it an answer back in 2015 (#4487426)Torrential
Thank you for your answer, for me, the other solutions did not work for objects nested in arrays!Mowery
@Mowery This was my case, too. Only this solution worked well because I had to delete a field with array after finding a specific document's idIggie
Note that the string is a path to the key. So, if the object you want to delete is nested, you must path to it. This answer solved my problem!Harmonica
G
12

At mongo syntax to delete some key you need do following:

{ $unset : { field : 1} }

Seems at Mongoose the same.

Edit

Check this example.

Gaia answered 20/12, 2010 at 9:2 Comment(2)
Can you clarify this answer and give a code example that relates to the example code above?Sihonn
sorry but i am not expereinced at mongoose. Above syntax it's mongo syntax, so i suppose that driver for any language support this. I found some example, check it in my answer.Gaia
D
3

if you want to remove a key from collection try this method.

 db.getCollection('myDatabaseTestCollectionName').update({"FieldToDelete": {$exists: true}}, {$unset:{"FieldToDelete":1}}, false, true);
Doublestop answered 20/6, 2019 at 6:3 Comment(1)
I don't believe the question was about removing the field from all documents in the collection, which is what this doesAras
I
2

Try:

User.findOne({}, function(err, user){
  // user.key_to_delete = null; X
  `user.key_to_delete = undefined;`

  delete user.key_to_delete;

  user.save();
});
Inexistent answered 19/4, 2020 at 19:48 Comment(0)
T
1

Could this be a side problem like using

function (user)

instead of

function(err, user)

for the find's callback ? Just trying to help with this as I already had the case.

Tennison answered 12/4, 2011 at 20:46 Comment(0)
M
1

Mongoose document is NOT a plain javascript object and that's why you can't use delete operator.(Or unset from 'lodash' library).

Your options are to set doc.path = null || undefined or to use Document.toObject() method to turn mongoose doc to plain object and from there use it as usual. Read more in mongoose api-ref: http://mongoosejs.com/docs/api.html#document_Document-toObject

Example would look something like this:

User.findById(id, function(err, user) {
    if (err) return next(err);
    let userObject = user.toObject();
    // userObject is plain object
});
Menedez answered 21/6, 2018 at 19:52 Comment(0)
U
1

the problem with all of these answers is that they work for one field. for example let's say i want delete all fields from my Document if they were an empty string "". First you should check if field is empty string put it to $unset :

function unsetEmptyFields(updateData) {
  const $unset = {};
  Object.keys(updatedData).forEach((key) => {
    if (!updatedData[key]) {
      $unset[key] = 1;
      delete updatedData[key];
    }
  });
  updatedData.$unset = $unset;

  if (isEmpty(updatedData.$unset)) { delete updatedData.$unset; }

  return updatedData;
}

function updateUserModel(data){
const updatedData = UnsetEmptyFiled(data);

    const Id = "";
    User.findOneAndUpdate(
      { _id: Id },
      updatedData, { new: true },
    );
}

Undermost answered 20/2, 2019 at 6:28 Comment(0)
D
-6

you can use delete user._doc.key

Dumbarton answered 18/10, 2016 at 11:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.