wlh
wlh

Reputation: 3515

Create subsubdocs in Mongoose with Nested Schema

I have a User Schema that includes nested Schemas - overall three layers deep. I have no problem adding to Polls, but cannot add Inputs for the life of me. I have tried to get a user then handle the data like regular json (such as getting the index of the polls array and then pushing to the nested input array). I have tried creating a new input and pushing it to the inputs array.

The following code works perfectly for creating a new poll on a given user:

const poll = user.polls.create({});
user.polls.push(poll);
user.save(function(err, data) {
   //more stuff here
})

However, when I try the same method on polls, I cannot save to the DB.

const poll = user.polls.id(<some _id>);
const input = poll.create({}); // or user.polls.id(<some _id>).create({});
poll.inputs.push(input);

I have gone back and forth and tried several things and cannot seem to get this to work given my current data structure. I have read several posts on SO as well as other online sources but most give examples for the first embedded subdoc, not the subdoc of the subdoc. Any help you can provide would be greatly appreciated. Thanks. I'm thinking of scrapping Mongoose on this project and just using the mongodb package for clearer control over what is going on with my data.

Here's my current code:

From User.js

const InputSchema = new Schema({
    [ALL SORTS OF VARIOUS DATA HERE] 
});

const PollSchema = new Schema({
    inputs: [InputSchema],
});

const UserSchema = new Schema({
    polls: [PollSchema]
});

module.exports = mongoose.model('User', UserSchema);

From controllers.js

const User = require('../models/User');

router.post('/polls/inputs/add/:creatorId', function(req, res) {
    let title = req.body.option.title,
        order = req.body.option.order,
        voters= [];

    User.findOne({ creatorId: req.params.creatorId })
        .then(user => {

            const input = {order, title, voters};

            user.polls.id(req.body.pollId).inputs.push(input);

            user.save(function(err, data) {
                if (err) {
                    res.statusCode = 500;
                    return res.json({ title: 'Save Error', message: err });
                }
                console.log('Success!');
                res.json({ input: input });
            });
        }).catch(err => {
            res.statusCode = 500;
            return res.json({ title: 'DB Error', message: err });
        });;
});

Upvotes: 0

Views: 287

Answers (1)

danielm
danielm

Reputation: 339

Mongoose isn't able to track changes in subobjects like this, so the field must be marked explicitely as needing to be updated like so:

user.markModified('polls')

Upvotes: 1

Related Questions