'POST to mongoose DB with Nested schema

I have an inventory schema with item subschema as below:

const ItemSchema = new mongoose.Schema(
{
    name: { //Full name of product
        type: String,
    },
    type: { //Beer? Wine? Liquor? Cider?
        type: String,
    },
    unit: { //What is the minimum amount you can order? 
        type: Number,
    },
    volume: { //How much liquid is in it?(in mL)
        type: Number,
    },
    packaging: {
        type: String,
    },
    quantity: {
        type: Number,
    },
    price: {
        type: Number,
    },   
},
{
    timestamps: true,
}

const InventorySchema = new mongoose.Schema(
{
    user: { 
        type: mongoose.Schema.Types.ObjectId,
        required: [true, 'Need user ID'],
        ref: 'User'
    },
    items: {
        type: [ItemSchema],
        default: []
    }
},
{
    timestamps: true,
}

I am building an API to add subschema Item, but how do I do it?

const addItem = asyncHandler(async (req, res) => {
//req.user.id is given by authentication middleware
//req.body is the ItemSchema object
if (!req.user.id) {
    res.status(400);
    throw new Error('Cannot add without ID')
}
const newItem = {
    user: req.user.id,
    items: await ItemModel.create(req.body),
}

res.status(200).send(newItem)

This is what I have ATM, but I don't think I am doing it right. I get "Cannot read properties of undefined (reading 'create')" response.



Solution 1:[1]

First of all, When creating a schema, if you only have a regular type, just write the types, no need for all the overheads-

const ItemSchema = new mongoose.Schema({
 name: String,
 type: {type: String},
 unit: Number... etc..
}

also, arrays default value are empty arrays so you don't need to tell this to mongoose. so you can just do in your InventorySchema:

items:[ItemSchema]

regarding your question, First, you need to create Models out of your schemas. So for example:

const InventoryModel = new mongoose.model('Inventory', InventorySchema);

and also do it for the item schema

and then create a new item from it, and in your controller:

...
...
const newItem = new ItemModel({....});
const newInventory = new InventoryModel({user: req.user.id,});
newInventory.items.push(newItem);
newInventory.save(); 
...
...

Than the new inventory is saved in your DB and you can do whatever you want with it

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1