How to remove item in nested collection by id - mongoose

Viewed 112

I want to remove a topic by id from the following collection. Here is the hierarchy of the collection - Area.

Area ---
     |
     ---Subjects---
                 |
                 Courses---
                          |
                          Chapters----
                                     |
                                     Topics

The Area example is as following.

{
    "_id" : ObjectId("607f7c67f64e993a5c9b9793"),
    "name" : "Automatic Engineering",
    "description" : "this is the description.",
    "created" : ISODate("2021-04-21T01:14:15.736Z"),
    "subjects" : [ 
        {
            "description" : "dddd",
            "name" : "Transfer Function",
            "_id" : ObjectId("607f7c7af64e993a5c9b9794"),
            "created" : ISODate("2021-04-21T01:14:34.943Z"),
            "courses" : [ 
                {
                    "description" : "dddd",
                    "name" : "conception",
                    "_id" : ObjectId("607f7c9af64e993a5c9b9796"),
                    "created" : ISODate("2021-04-21T01:15:06.696Z"),
                    "chapters" : [ 
                        {
                            "description" : "chapter 1",
                            "name" : "Chapter 1",
                            "_id" : ObjectId("607f7cb4f64e993a5c9b9798"),
                            "created" : ISODate("2021-04-21T01:15:32.855Z"),
                            "topics" : [ 
                                {
                                    "description" : "1",
                                    "name" : "Topic 1",
                                    "_id" : ObjectId("607f7ccef64e993a5c9b979b"),
                                    "created" : ISODate("2021-04-21T01:15:58.064Z")
                                }, 
                                {
                                    "description" : "2",
                                    "name" : "Topic 2",
                                    "_id" : ObjectId("607f7cd5f64e993a5c9b979c"),
                                    "created" : ISODate("2021-04-21T01:16:05.663Z")
                                }, 
                                {
                                    "description" : "3",
                                    "name" : "Topic 3",
                                    "_id" : ObjectId("607f7cdcf64e993a5c9b979d"),
                                    "created" : ISODate("2021-04-21T01:16:12.336Z")
                                }
                            ]
                        }, 
                        {
                            "description" : "chapter2",
                            "name" : "Chapter 2",
                            "_id" : ObjectId("607f7cbcf64e993a5c9b9799"),
                            "created" : ISODate("2021-04-21T01:15:40.231Z"),
                            "topics" : []
                        }, 
                        {
                            "description" : "chapter 3",
                            "name" : "Chapter 3",
                            "_id" : ObjectId("607f7cc5f64e993a5c9b979a"),
                            "created" : ISODate("2021-04-21T01:15:49.000Z"),
                            "topics" : []
                        }
                    ]
                }, 
                {
                    "description" : "dddd",
                    "name" : "exercise",
                    "_id" : ObjectId("607f7ca6f64e993a5c9b9797"),
                    "created" : ISODate("2021-04-21T01:15:18.465Z"),
                    "chapters" : []
                }
            ]
        }, 
        {
            "description" : "this is the example",
            "name" : "State Space Equation",
            "_id" : ObjectId("607f7c8ef64e993a5c9b9795"),
            "created" : ISODate("2021-04-21T01:14:54.056Z"),
            "courses" : []
        }
    ],
    "__v" : 0
}

And I need to remove topic object in chapters array. So this is what I have done.

areaModel.findOneAndUpdate({
    '_id': req.body.area_id,
    'subjects._id': req.body.subject_id,
    'courses._id': req.body.course_id,
    'chapter._id': req.body.chapter_id
}, {
    "$pull": {
        "subjects.$.courses.$.chapters.$.topics": {
            _id: req.body.topic_id
        }
    }
},  (err, result) =>{
    if (err) {
        return res.json({success: false, msg: err});
    } else {
        return res.json({success: true, msg:"successfully removed" });
    }
});

By using $pull method of mongoose, I could remove the course from the area easily. But it was impossible for me to remove the more nested items like chapters and topics.

How can I solve this issue?

2 Answers

Try it:

areaModel.findOneAndUpdate(
  { _id: req.body.area_id },
  {
    $pull: {
      "subjects.$[].courses.$[].chapters.$[].topics": {
        _id: req.body.topic_id,
      },
    },
  }
);

you can do so with the use of arrayFilters like so:

db.collection.updateOne(
{
    _id: ObjectId("607f7c67f64e993a5c9b9793")
},
{
    $pull: {
        "subjects.$[s].courses.$[c].chapters.$[ch].topics": {
            _id: ObjectId("607f7ccef64e993a5c9b979b")
        }
    }
},
{
    arrayFilters: [
        {
            "s._id": { $eq: ObjectId("607f7c7af64e993a5c9b9794") }
        },
        {
            "c._id": { $eq: ObjectId("607f7c9af64e993a5c9b9796") }
        },
        {
            "ch._id": { $eq: ObjectId("607f7cb4f64e993a5c9b9798") }
        }
    ]
})

https://mongoplayground.net/p/kVyV27nnkII

Related