Search code examples
node.jsmongodbmongoosemongoose-schemamongoose-populate

Mongoose create with push for multiple refs


So have a kind of nested structure with my DB here is my three schemas : User Schema:

var UserSchema = new mongoose.Schema({

    email: {
        type: String,
        lowercase: true,
        unique: true,
        required: true
    },
    password: {
        type: String,
        required: true
    },
    role: {
        type: String,
        enum: ['trainer', 'client', 'admin'],
        default: 'client'
    },
    trainer: {
        type: mongoose.Schema.Types.ObjectId, 
        ref: 'User'
    },
    programs:  [
       {
                type: mongoose.Schema.Types.ObjectId, 
                ref: 'Program'
            }
        ],
    diet:   [
    {
        calories: {
            type: Number
        },
        protein: {
            type: Number
        },
        fats: {
            type: Number
        },
        carbs: {
            type: Number
        },
        fiber: {
            type: Number
        }
    }],
    stats: 
       {
          bodyweight: 
              [ {
                  _id: false,
                  measurement:{ type: Number},
                 time : { type : Date, default: Date.now }
              }
              ]
        },
    name: {
        type: String,
        required: true
    },

}, {
    timestamps: true
});

Program schema:

var ProgramSchema = new mongoose.Schema({

    title: {type: String, required: true},
    description: {type: String, required: true},
    createdby: {
        type: mongoose.Schema.Types.ObjectId, 
        ref: 'User'
    }, 
    exercises: [
        {
            exercise:{
                type: mongoose.Schema.Types.ObjectId, 
                ref: 'Exercise'
            },
            sets:{
                type: Number
            }
        } 
        ]
}, {
    timestamps: true
});

And Exercise schema:

var ExerciseSchema = new mongoose.Schema({

    name: {
        type: String,
        lowercase: true,
        unique: true,
        required: true
    },
    description: {
        type: String,
        required: true
    },
    video: {
        type: String
    },
    image: {
        type: String
    }

}, {
    timestamps: true
});

As you can see , a user can have many programs and a program can have many exercises. But when i return a user object, even using the populate function, the exercises within a users programs are not populated. I beleive this is down to how i create a program, from my understanding i have to push the exercise objects into the program, but i'm not sure how i would create a program and push exercises into it at the same time. This is my current create program program function:

exports.createProgram = function(req, res, next){

    Program.create({
        title : req.body.title,
        description: req.body.description,
        exercises: req.body.exercises,
        createdby: req.body.createdby

    }, function(err, program) {

        if (err){
            res.send(err);
        }

        Program.find(function(err, programs) {

            if (err){
                res.send(err);
            }

            res.json(programs);

        });

    });

}

Is there a way i can do some kinda of forEach on req.body.exercises maybe? Thanks in advance Also here is how i return users:

exports.getClients = function(req, res, next){

        var trainerid = req.params.trainerid;


   User.find({trainer: trainerid})
        .populate({
            path: 'programs',
            populate: { path: 'exercises' }
        })
        .exec(function (err, clients) {
            if (err) return handleError(err);
        console.log(clients);
        res.json(clients);
        });

}

Solution

  • I think you are on the right path, but you have populated exercise wrong. Instead of populating exercises, you need to populate exercises.exercise.

    Try this:

    User.find({trainer: trainerid})
        .populate({
            path: 'programs',
            populate: { path: 'exercises.exercise' }
        })
        .exec(function (err, clients) {
            if (err) return handleError(err);
        console.log(clients);
        res.json(clients);
        });