Stephen Agwu
Stephen Agwu

Reputation: 1023

Accessing nested documents within nested documents

I'm having a problem that is really bugging me. I don't even want to use this solution I don't think but I want to know if there is one.

I was creating a comment section with mongodb and mongoose and keeping the comments attached to the resource like this:

const MovieSchema = new mongoose.Schema({
  movieTitle: {type: String, text: true},
  year: Number,
  imdb: String,
  comments: [{
    date: Date,
    body: String
  }]
})

When editing the comments body I understood I could access a nested document like this:

const query = {
    imdb: req.body.movie.imdb,
    "comments._id": new ObjectId(req.body.editedComment._id)
}

const update = {
    $set: {
        "comments.$.body": req.body.newComment
    }
}

Movie.findOneAndUpdate(query, update, function(err, movie) {
    //do stuff
})

I then wanted to roll out a first level reply to comments, where every reply to a comment or to another reply just appeared as an array of replies for the top level comment (sort of like Facebook, not like reddit). At first I wanted to keep the replies attached to the comments just as I had kept the comments attachted to the resource. So the schema would look something like this:

const MovieSchema = new mongoose.Schema({
    movieTitle: {type: String, text: true},
    year: Number,
    imdb: String,
    comments: [{
        date: Date,
        body: String,
        replies: [{
            date: Date,
            body: String
        }]
    }]
})

My question is how would you go about accessing a nested nested document. For instance if I wanted to edit a reply it doesn't seem I can use two $ symbols. So how would I do this in mongodb, and is this even possible?

I'm pretty sure I'm going to make Comments have its own model to simplify things but I still want to know if this is possible because it seems like a pretty big drawback of mongodb if not. On the other hand I'd feel pretty stupid using mongodb if I didn't figure out how to edit a nested nested document...

Upvotes: 1

Views: 143

Answers (1)

Igal Klebanov
Igal Klebanov

Reputation: 368

according to this issue: https://jira.mongodb.org/browse/SERVER-27089

updating nested-nested elements can be done this way:

parent.update({}, 
    {$set: {“children.$[i].children.$[j].d”: nuValue}}, 
    { arrayFilters: [{ “i._id”: childId}, { “j._id”: grandchildId }] });

this is included in MongoDB 3.5.12 development version, in the MongoDB 3.6 production version.

according to https://github.com/Automattic/mongoose/issues/5986#issuecomment-358065800 it's supposed to be supported in mongoose 5+


if you're using an older mongodb or mongoose versions, there are 2 options:

find parent, edit result's grandchild, save parent.

const result = await parent.findById(parentId);

const grandchild = result.children.find(child => child._id.equals(childId))
    .children.find(grandchild => grandchild._id.equals(grandchildId));

grandchild.field = value;

parent.save();

know granchild's index "somehow", findByIdAndUpdate parent with:

parent.findByIdAndUpdate(id,
    { $set: { [`children.$.children.${index}.field`]: value }});

Upvotes: 1

Related Questions