20

I'm trying to remove an object from an array in a document using mongoose.

The Schema is the following:

var diveSchema = new Schema({
//irrelevant fields
    divers: [{
        user: { type: Schema.Types.ObjectId, ref: 'User', required: true },
        meetingLocation: { type: String, enum: ['carpool', 'onSite'], required: true },
        dives: Number,
        exercise: { type: Schema.Types.ObjectId, ref: 'Exercise' },
    }]
});

a possible entry can be

{
    //irrelevant fields
    "divers": [
        {
            "_id": "012345678",
            "user": "123456789",
            "meetingLocation": "carpool",
            "exercise": "34567890",
        },
        {
            "_id": "012345679",
            "user": "123456780",
            "meetingLocation": "onSite",
            "exercise": "34567890",
        }
    ]
}

Say I want to remove the entry where user is 123456789 (note I do not know the _id at this point).

How do I do this correctly?

I tried the following:

        var diveId = "myDiveId";
        var userIdToRemove = "123456789"
        Dive.findOne({ _id: diveId }).then(function(dive) {
            dive.divers.pull({ user: userIdToRemove });
            dive.save().then(function(dive) {
                //do something smart
            });
        });

This yieled no change in the document.

I also tried

Dive.update({ _id: diveId }, { "$pull": { "divers": { "diver._id": new ObjectId(userIdToRemove) } } }, { safe: true }, function(err, obj) {
    //do something smart
});

With this I got as result that the entire divers array was emptied for the given dive.

5 Answers 5

39

What about this?

Dive.update({ _id: diveId }, { "$pull": { "divers": { "user": userIdToRemove } }}, { safe: true, multi:true }, function(err, obj) {
    //do something smart
});
Sign up to request clarification or add additional context in comments.

4 Comments

this seems to work! thanks, but can you also explain what I did wrong, because I did try to just use user before, but I didn't add the multi part
How is this option { safe: true, multi:true } helpful when you have an update operation that queries a single document { _id: diveId }?
@chridam , you are right, for single document and $pull it would be overkill to use multi:true , but to be honest, I have come across some drivers which stops executing as soon as it does just one operation (not document) if you don't provide multi as true. For example if you call $set inside an array, the driver just sets the first element of array for some driver. That's the reason I use it. You can avoid it.
@Sonaryr if you did try this same query, maybe the reason it didn't work is mentioned in my previous comment, it all basically boils down how your driver has implemented the operations.
6

I solve this problem using this code-

 await Album.findOneAndUpdate(
    { _id: albumId },
    { $pull: { images: { _id: imageId } } },
    { safe: true, multi: false }
  );
  return res.status(200).json({ message: "Album Deleted Successfully" });

1 Comment

This is awesome. It's worked for me.
0

Try this

Dive.update({ _id: diveId },{"$pull": { "drivers": {"user": "123456789"}}})

1 Comment

Same answer as above.
0

Try this async code

var diveId = "myDiveId";
var userIdToRemove = "123456789"
const dive=await Dive.findOne({ _id: diveId })
await dive.divers.pull({ user: userIdToRemove });
await dive.save();

1 Comment

Welcome to Stack Overflow! Your answer might be more helpful to others if you explained how/why it works, and/or why this solution is better than the existing answers that have already been here for a while :)
0

Use this with try/catch:

await Group.updateOne(
  { _id: groupId },
  { $pull: { members: {id: memberId }}}
);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.