Mongoose - delete subdocument array item
Asked Answered
C

3

11

I have this little schema for users:

{
 username: String,
 contacts: Array
}

So for example some user's contacts will look like this:

{
 username: "user",
 contacts: [{'id': ObjectId('525.....etc'), 'approved': false}, {'id':ObjectId('534.....etc'), 'approved': true}]
}

Now I need to delete an item from contacts so I do:

model.findByIdAndUpdate(23, {'$pull': {
              'contacts':{'id':'525.....etc'}
              }});

but seems not working, no errors but it doesn't gets deleted, I just would like to return this document for the user:

{
     username: "user",
     contacts: [{'id':ObjectId('534.....etc'), 'approved': false}]
    }

how to achieve this?

Convivial answered 8/10, 2014 at 8:40 Comment(0)
E
17

The $pull operator actually just performs the conditions on the array element on which it is operating. It seems that your question might not actually show that you are probably working with an ObjectId value that mongoose creates by default for all array fields.

So you could to your query like this, after importing the ObjectId creation method:

model.findByIdAndUpdate(23, {
    '$pull': {
        'contacts':{ '_id': new ObjectId(someStringValue) }
    }
});

Or in fact you can actually define your "schema" a little better, and mongoose will actually "autocast" the ObjectId for you based on the "type" defined in the schema:

var contactSchema = new Schema({
    approved: Boolean
});

var userSchema = new Schema({
    username: String,
    contacts: [contactSchema]
});

This allows mongoose to "follow the rules" for strictly typed field definitions. So now it knows that you actually have an _id field for each element of the contacts array, and the "type" of that field is actually an ObjectId so it will automatically re-cast "String" values supplied as a true ObjectId.

Eboat answered 8/10, 2014 at 8:45 Comment(6)
hi thanks but now i got this error : [MongoError: exception: cannot use the part (contacts of contacts.id) to traverse the element ({contacts: [ { id: ObjectId('543394bb964ac60915ceba8b'), approved: false }, { id: ObjectId('543399f9964ac60915ceba8c'), approved: false } ]}) what this could be? i used your dot annotation –Convivial
@sbaaaang What are you actually doing? Are you using the "dot notation" form as you were told to? BTW Thanks for clearly showing that your actual data differs from how you posted which is probably part of the problem here again. Please edit to show your real data structure.Eboat
yes using dot notation like u said, yes im using ObjectIds but well that is not the problem i guess :P nope? (edited question)Convivial
ok fixed it works as i posted in question just needed to wrap new ObjectId(idContact) when querying ;) thank you ! please edit the answer so i can accept itConvivial
to be clear model.findByIdAndUpdate(23, {'$pull': { 'contacts':{'id': new ObjectId('525.....etc')} }}); WORKSConvivial
@sbaaaang Should have paid more attention that you were using mongoose really. There is a certain way to do things that you don't seem to be aware of that you can learn from. You don't need to manually "cast" when you do things as are displayed. This is why you should post your "real data" and "query" in questions. Don't make it up.Eboat
Q
4

finaly!

MongoDB:

"imgs" : {"other" : [ {
        "crop" : "../uploads/584251f58148e3150fa5c1a7/photo_2016-11-09_21-38-55.jpg",
        "origin" : "../uploads/584251f58148e3150fa5c1a7/o-photo_2016-11-09_21-38-55.jpg",
        "_id" : ObjectId("58433bdcf75adf27cb1e8608")
                                    }
                            ]
                    },
router.get('/obj/:id',  function(req, res) {
var id = req.params.id;



Model.findOne({'imgs.other._id': id}, function (err, result) {
        result.imgs.other.id(id).remove();
        result.save();            
    });
Quinnquinol answered 4/12, 2016 at 1:32 Comment(0)
Q
0

Is 23 in the query referencing the placement in the array or is that the is for the model?

model.findByIdAndUpdate(23, {
  '$pull': {
    'contacts':{ '_id': new ObjectId(someStringValue) }
  }
});
Quill answered 4/7, 2023 at 16:46 Comment(1)
Answer is unclear Is this an answer or a question? As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Sn

© 2022 - 2024 — McMap. All rights reserved.