Search code examples
node.jsmongodbmongoosemongoose-schema

Category and Subcategory in mongodb using mongoose


I'm creating an ecommerce website using nodejs. Ideally, the product will have a category and subcategory. But what I'm creating should be used with any type of ecommerce website, and therefore, the subcategory field might not be needed.

In the product schema I added the subcategory field, which is related to the subcategory document. And the subcategory document is related to the category document.

My question is, how can a product be added in the database without a subcategory?

Category schema:

const categorySchema = mongoose.Schema({
    name: {
        type: String,
        required: true,
    }
})

module.exports = mongoose.model('Category', categorySchema);

Subcategory schema:

const subCategorySchema = mongoose.Schema({
    name: {
        type: String,
        required: true,
    },
    Category: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'Category',
        required:true
    },
})

module.exports = mongoose.model('SubCategory', subCategorySchema);

Product schema:

const productSchema = mongoose.Schema({
    name: {
        type: String,
        required: true,
    },
    description: {
        type: String,
        required: true
    },
    price : {
        type: Number,
        default:0
    },
    SubCategory: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'SubCategory',
        required:true
    },
    countInStock: {
        type: Number,
        required: true,
        min: 0,
        max: 255
    },
})


module.exports = mongoose.model('Product', productSchema);

Thanks in advance...


Solution

  • I'm afraid you're going to have to have a required Category field in your ProductSchema and a non-required SubCategory field. This way, you'll make sure that all your products have, at least, a Category, and allow for a SubCategory to be added:

    const productSchema = mongoose.Schema({
      name: {
          type: String,
          required: true,
      },
      description: {
          type: String,
          required: true
      },
      price : {
          type: Number,
          default:0
      },
      Category: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'Category',
        required: true
      },
      SubCategory: {
          type: mongoose.Schema.Types.ObjectId,
          ref: 'SubCategory',
          required: false
      },
      countInStock: {
          type: Number,
          required: true,
          min: 0,
          max: 255
      },
    })
    

    If you want to make sure that the hierarchy of the category and subcategory, you can always add some middleware validation on your pre-save:

    productSchema.pre('save', async function (next) {
      if (this.SubCategory) {
        try {
          const check = await SubCategory.findById(this.SubCategory);
          if (!check || JSON.stringify(check.Category) !== JSON.stringify(this.Category)) {
            throw new Error('Check your Category and/or SubCategory');
          }
        } catch (error) {
          throw error;
        }
      }
      next();
    });