2

i have the following document , it has two array's , one inside the other ,
attachment array and files array inside attachment array . i want to delete an element inside files array using this element _id . but its not working with me , i tried this code , it return { n: 144, nModified: 0, ok: 1 }

   Invoice.update({}, {
        $pull: {
            "attachment":
            {
                "files":
                {
                    $elemMatch:
                        { _id: ObjectId("5b7937014b2a961d082de9bf") }
                }
            }
        }
    }, { multi: true })
        .then(result => {
            console.log("delete", result);


        });

this is how the document looks like document

8
  • @AnthonyWinzlet thanks , but the post is different , i have 2 arrays and i want to delete element inside the second array that exist in the first array . Commented Aug 19, 2018 at 10:18
  • Try Invoice.update( {}, { "$pull": { "attachment.$[].files":{_id:ObjectId("5b7969ac8fb15f3e5c8e844e") } }}, { "multi": true } , function (err, result) { console.log(result); }); Commented Aug 19, 2018 at 13:18
  • { ok: 0, n: 0, nModified: 0 } { MongoError: cannot use the part (attachment of attachment.$[].files) to traverse the element ({attachment: []}) Commented Aug 19, 2018 at 13:22
  • What is your mongo server version ? You need 3.6. Also you may need to run admin command from shell db.adminCommand( { setFeatureCompatibilityVersion: 3.6 or 4.0 depending on your version } ) Commented Aug 19, 2018 at 13:27
  • MongoDB shell version v3.4.13 connecting to: mongodb://127.0.0.1:27017 MongoDB server version: 3.4.13 do i need to run the command? Commented Aug 19, 2018 at 13:34

3 Answers 3

4

You can try below update query in 3.6 version.

Invoice.update( 
 {}, 
 {"$pull":{"attachment.$[].files":{_id:ObjectId("5b7969ac8fb15f3e5c8e844e")}}}, 
 {"multi": true}, function (err, result) {console.log(result);
});

Use db.adminCommand( { setFeatureCompatibilityVersion: 3.6 or 4.0 depending on your version } ) if your are upgrading from old version.

Sign up to request clarification or add additional context in comments.

3 Comments

What if i want to find this file using the id ? i tried to do this but it did not work , Invoice.find({ "attachment.$[].files": { _id: ObjectId(fileId) } }, function (err, result) { console.log("**", result) });
Try Invoice.find({ "attachment.files": { _id: ObjectId(fileId) } }, function (err, result) { console.log("**", result) });
nope it did not work it return empty array , i tried this and it work but i am not sure if this is a best way to do it Invoice.findOne({ "attachment.files._id": ObjectId(fileId) }, { 'attachment.files.$': 1 }, async function (err, result) {console.log("**",result)});
4

For Mongodb version prior to 3.6

There is only one nested level here so you can simply use $ positional operator.

Invoice.update(
  { "attachment.files._id": mongoose.Types.ObjectId("5b7937014b2a961d082de9bf") },
  { "$pull": { "attachment.$.files": { "_id": mongoose.Types.ObjectId("5b7937014b2a961d082de9bf") }}},
  { "multi": true }
)

For Mongodb version 3.6 and above

If you want to update multiple elements inside attachement array then you can use $[] the all positional operator.

const mongoose = require("mongoose")

Invoice.update(
  { "attachment.files._id": mongoose.Types.ObjectId("5b7937014b2a961d082de9bf") },
  { "$pull": { "attachment.$[].files": { "_id": mongoose.Types.ObjectId("5b7937014b2a961d082de9bf") }}},
  { "multi": true }
)

And If you want to update single element inside the attachment array then you can use $[<identifier>] that identifies the array elements that match the arrayFilters conditions.

Suppose you want to update only an element inside attachment having _id equal to ObjectId(5b7934f54b2a961d081de9ab)

Invoice.update(
  { "attachment.files._id": mongoose.Types.ObjectId("5b7937014b2a961d082de9bf") },
  { "$pull": { "attachment.$[item].files": { "_id": mongoose.Types.ObjectId("5b7937014b2a961d082de9bf") } } },
  { "arrayFilters": [{ "item._id": mongoose.Types.ObjectId("5b7934f54b2a961d081de9ab") }], "multi": true }
)

5 Comments

@Winzlet it did not work .. i got this { ok: 0, n: 0, nModified: 0 }
You need to cast your id to object id... Just I did above
i did like this , same thing . const mongoose = require('mongoose'); const ObjectId = mongoose.Types.ObjectId; Invoice.update( { "attachment.files._id": ObjectId("5b7969ac8fb15f3e5c8e844e") }, { "$pull": { "attachment.$[].files.$[]._id": ObjectId("5b7969ac8fb15f3e5c8e844e") } }, { "multi": true } , function (err, result) { console.log(result); });
@AhmadKhalaf I have updated the answer... Please have a look
i updated to 3.6 and as Veeram said using the same code you both provided it work perfect ^^ thanks
0

I faced with the same issue and got another solution:

const modelA = await Model.findOne(...)
modelA.array1[0].nestedArray[1] = 'test value'
await modelA.update(modelA.toObject())

Comments