Home > other >  How do I add a subdocument's data to a parent document (using mongoose)?
How do I add a subdocument's data to a parent document (using mongoose)?

Time:04-14

I am creating a MERN app and have a series of mongoose schema that are connected.

The hierarchy goes: Program -> Workout -> Exercise -> Set

Here is the model code for each Schema:

Program Schema

const programSchema = mongoose.Schema({

program_name:{
    type: String,
},
workouts:[{
    type: mongoose.Types.ObjectId,
    ref: 'Workout'
}]

Workout Schema

const workoutSchema = mongoose.Schema({
workout_name:{
    type:String
},
exercises: [{
    type: mongoose.Types.ObjectId,
    ref: 'Exercise'
}]

Exercise Schema

const exerciseSchema = mongoose.Schema({
exercise_name:{
    type:String
},
notes:{
    type:String
},
sets:[{
    type: mongoose.Types.ObjectId,
    ref: 'Set'
}]

Set Schema

const setSchema = mongoose.Schema({
weight:{
    type: String
},
repetitions:{
    type: String
},
rpe:{
    type: String
}

My question is, now that they are all separate. How do I link a specific Set to a Exercise? or a specific Exercise to a Workout? etc. How do I reference them to each other so that I can create a whole program with various workouts, and each workout having various exercises, etc. I would appreciate any wisdom. Thank you

For more info, here are the controllers.

Program Controller (CREATE NEW PROGRAM)

const createProgram = async (req, res) => {

//const {program_name, workouts} = req.body

try {
    const program = new Program(req.body) // create a new program with the information requested
    await program.save() // save it to database
    res.status(201).send(program) // send it back to user
} catch (e) {
    res.status(500).send(e)
}

WORKOUT CONTROLLER (CREATE NEW WORKOUT)

const createWorkout = async (req, res) => {

const {workout_name} = req.body

try {
    const workout = await new Workout({
        workout_name
    })
    await workout.save()
    res.status(201).send(workout)

} catch(e) {
    
}

EXERCISE CONTROLLER (CREATE NEW EXERCISE)

const createExercise = async (req, res) => {

const { exercise_name='', notes='', sets } = req.body

try {
    const exercise = await new Exercise({
        exercise_name,
        notes,
        sets
    })
    await exercise.save()
    res.status(201).send(exercise)
} catch (e) {
    console.log(e)
}

SET CONTROLLER (CREATE NEW SET)

const createSet = async (req, res) => {
const {repetitions='', weight='', rpe=''} = req.body
try {
    const set = await new Set({
        weight,
        repetitions,
        rpe
    })
    await set.save()
    res.status(201).send(set)
} catch (e) {
    res.status(500).send(e)
}

CodePudding user response:

The way I do it is on save I add the id to the attributed array. So i'll give you an example for one of your Routers then hopefully you can understand enough to do the rest.

For workouts you want to add it to a program when it's created. so when you create it, just add the id to the program you want to add it to.

Like so:

const {workout_name} = req.body

try {
    const newWorkout = await Workout.create({
        workout_name
    })

    Program.updateOne(
      { _id: req.params.ProgramId },
      { $addToSet: { workouts: newWorkout._id }},
    )
    
    res.status(201).send(workout)

} catch(e) {
    
}

So basically after creating your workout, you add that workout ID to the workouts array of the parent object. You would do the same for the rest of your Routers.

  • Related