Francesco Russo
Francesco Russo

Reputation: 47

Mongoose Trouble Adding Subdocs to Array

I am looking to push to an array on my users schema in mongoose. I am following mongoose's Adding Subdocs to Arrays documentation but keep getting an error on user.notes.push(newNotebook)

TypeError: Cannot read properties of undefined (reading 'push')

Here is my setup:

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


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

...

const user = User.findOne({ userId })

const newNotebook = { userId: userId, notebookId: notebookId, title: title, numNotes: 0 }

user.notebooks.push(newNotebook)
        
}

Any help would be much appreciated.

Update--

Here is the solution:

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


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

...

const user = User.findOne({ userId })

if (!user) return

const newNotebook = { userId: userId, notebookId: notebookId, title: title, numNotes: 0 }

user.notebooks = user.notebooks || []; // returns user.notebooks if defined else empty array

user.notebooks.push(newNotebook)

await user.save()
        
}

Big thanks to Mandeep for showing me the !user condition and .save() method. Special thanks to Sardar for bringing the user.notebooks = user.notebooks || [] solution to light.

Disclaimer: upon watching this video on MongoDB anti patterns, I learned nesting boundless data under a single document can be problematic since each MongoDB document is limited to 16mb. It is also supposedly inefficient relative to saving your data in respective collections. Use caution when adding subdocs to arrays.

Upvotes: 1

Views: 54

Answers (2)

Sardar
Sardar

Reputation: 221

This is probably caused because "notebooks" is undefined by default for your userModel/schema

You can resolve this by two methods

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


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

  ...

  const user = User.find({
    userId
  })

  const newNotebook = {
    userId: userId,
    notebookId: notebookId,
    title: title,
    numNotes: 0
  }
  user.notebooks = user.notebooks || []; // returns user.notebooks if defined else empty array
  user.notebooks.push(newNotebook)

}

RECOMMENDED Or you can set default value for notebooks in your userModel like this (might not update your existing user documents) How to set default value in schema mongoose?

Upvotes: 1

Mandeep
Mandeep

Reputation: 364

It would be like this:

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

  const user = await User.find({
    userId
  }).limit(1).exec()

  if (!user) return

  const newNotebook = {
    userId: userId,
    notebookId: notebookId,
    title: title,
    numNotes: 0
  }

  user.notebooks.push(newNotebook)
  await user.save()
}

Upvotes: 1

Related Questions