The Art of Structuring MongoDB Schema

I have been diving into MongoDB through their online Webinar hosted on their platform and I am currently working on connecting Products to a Category (for example, associating iPhones with the Mobiles Category which falls under Electronics). However, as I attempt to nest them, I encounter the following error:

MongooseError: Schema hasn't been registered for model "Category".
Use mongoose.model(name, schema)

I have come across suggestions such as using Schema.ObjectId and Schema.Types.ObjectId, yet I still face a Cast Error to ObjectId when executing an insert(save) query.

There are some additional queries that arise in relation to this matter:

  1. How can I ensure that when adding a Product, the associated Category is also added?
  2. What would be the best approach for handling this situation (adding subdocuments or reference Schemas)?

Below are snippets from the Model files, followed by the Controller files I have developed to carry out CRUD operations:

category.js

var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var categorySchema = new Schema({
  _id: { type: String },
  parent: {
    type: String,
    ref: 'Category'
  },
  ancestors: [{
    type: String,
    ref: 'Category'
  }]
});

module.exports.categorySchema = categorySchema;

products.js

var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var Category = require('./category');
var fx = require('./fx');

var productSchema = new mongoose.Schema({
  name: { type: String, required: true },
  // Pictures must start with "http://"
  pictures: [{ type: String, match: /^http:\/\//i }],
  price: {
    amount: {
      type: Number,
      required: true,
      set: function(v) {
        this.internal.approximatePriceUSD =
          v / (fx()[this.price.currency] || 1);
        return v;
      }
    },
    // Only 3 supported currencies for now
    currency: {
      type: String,
      enum: ['USD', 'EUR', 'GBP'],
      required: true,
      set: function(v) {
        this.internal.approximatePriceUSD =
          this.price.amount / (fx()[v] || 1);
        return v;
      }
    }
  },
  category: { type: Schema.ObjectId,ref: 'Category'},
  internal: {
    approximatePriceUSD: Number
  }
});

//var schema = new mongoose.Schema(productSchema);

var currencySymbols = {
  'USD': '$',
  'EUR': '€',
  'GBP': '£'
};

/*
 * Human-readable string form of price - "$25" rather
 * than "25 USD"
 */
productSchema.virtual('displayPrice').get(function() {
  return currencySymbols[this.price.currency] +
    '' + this.price.amount;
});

productSchema.set('toObject', { virtuals: true });
productSchema.set('toJSON', { virtuals: true });

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

Illustrative Output Structure of a Product:

{
    "_id": "**autogeneratedByMongo",
    "name":"iPhone",
    "category":{
        "_id":"Mobiles", 
        "ancestors":["Electronics","Mobiles"]
    }
    ....
}

Answer №1

To establish a link to a specific ObjectId, update the type key with mongoose.Schema.Types.ObjectId. You can then reference the entire parent schema using .populate('parent').

For further details, please refer to: populate

Thank you.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What steps can I take to eliminate the '#' in my URLs when utilizing ui-router?

I have tried using $locationProvider and base href tag in the head of my index.html file, but I kept encountering a 404 error when trying to render my views. I believe the issue lies within the app.use method in my Express's app.js file. Here is the ...

What is the process for importing a module from node_modules?

Located within the node_modules directory is a subdirectory: data/lib/ This subdirectory contains the following files: index.js index.ts Data.js Data.ts How can we utilize this module with an import statement? I attempted to do so with the following c ...

In need of clarification on the topic of promises and async/await

I have been utilizing Promises and async/await in my code, and it seems like they are quite similar. Typically, I would wrap my promise and return it as needed. function someFetchThatTakesTime(){ // Converting the request into a Promise. return new ...

Running multiple web applications with different base directories on a single Express server

I am currently working on serving a website that requires different static directories for various routes. When a GET request is sent to the /tools* route, I want to utilize the /dist/toolsApp/ directory as the base directory for my frontend code. If ...

Ways in which you can retrieve a value from axios beyond the axios function

I have a router.get function that calls another function in the following way: router.get("/", (req, res) => { const data = especiaisTest.getEspeciais(); console.log(data); }); The function being called is defined as follows: function getEspeciais( ...

IntelliJ has removed the connect-flash plugin, preventing me from reinstalling it

Learning node.js is new to me and I encountered a strange issue. While working on implementing login functionality with passportjs, I faced an error where req.flash() was not functioning properly. Oddly enough, it was working fine yesterday when I used it ...

How can Sequelize be used to efficiently load data and exclude specific keys from the output?

Is there a way to exclude certain fields from the model in a find* query (such as password or token)? I've considered overriding the toJSON() function, but that may not be ideal since those fields are sometimes needed for validation or checking purpos ...

Notify using slack when a Firebase Cloud Functions deployment event occurs

Is there a way to automatically send a Slack message every time a deployment occurs on Firebase Cloud Functions? The message should include the project ID, functions that were deployed, and any deployment messages. I am proficient in sending Slack message ...

Error message net::ERR_CONNECTION_TIMED_OUT encountered while trying to establish a connection from an Angular frontend to a Node

I'm currently attempting to send a request from a containerized AngularJS frontend to a nodejs backend on AWS through Kubernetes (KOPS). I've set up a service to connect the two applications. In Kubernetes services, the frontend type is LoadBala ...

Type parameter in express.js route

If I have this specific route in my Express.js server: router.get('/ad/:id', (req, res) => { const { id } = req.params Ad.getAd(id, (err, resp) => { if(err){ return handleError('Failed to load an ad' ...

Running a Puppeteer node app on an Ubuntu Server as the root user: A Step-by-Step

When attempting to execute node applications utilizing the npm package Puppeteer for web scraping on VPSes with root as the default user, I encounter persistent issues. This recurring problem necessitates at least thirty minutes of online research in orde ...

What is the best method to create Promise API synchronously?

When it comes to testing with NodeJS, I rely on selenium-webdriver. My goal is to streamline the selenium-webdriver API by making it synchronous, which will result in more concise tests. The method getTitle() is used to retrieve the title of the current p ...

Issue with Heroku: Unable to serve images through NodeJS Express server

I have an app deployed on Heroku that displays an image. app.js package.json package-lock.json public |__ image1.png |__ image2.png This is the code within app.js const express = require('express'); const app = express(); const path = re ...

Every time I check Req.body, it always comes back empty, even after I've already entered information in my form

I am facing an issue with my form where I am trying to input a comment for my shoe and then send it to my node.js server through a POST request. However, the req.body.comment is consistently returning an empty string even when the form is filled out. In m ...

Why does Heroku keep saying it cannot locate the package.json file in my module every time I attempt to do a heroku push?

After creating my own npm package by forking react-coverflow, everything seemed to work perfectly when using it locally in my app with the command "npm install react-coverflow-mod" --save. I was able to run my app smoothly by selecting "run with debug (F5 ...

Tips for keeping my NodeJS application running indefinitely

I've developed a NodeJS application that interacts with an API and sends data to a specific endpoint only on weekdays at a particular time. While I could set up a cron job to execute the application at the designated time, I would rather have it cont ...

Top tips for deploying a MERN application on Amazon Web Services

It's a bit subjective and opinionated, but I'm just looking for a starting point to understand the best practices. Currently, I have a MERN application running on localhost with React script on port 3000 and an Express.js application on port 300 ...

A guide on integrating Swig templates with Express 4

I encountered an issue trying to utilize Swig templates with Express for Node.js. Whenever I attempt to render a view, the following error is thrown: Error: Failed to lookup view "index" in views directory It seems that the Swig templates are not being ...

What is the best way to set up jest to generate coverage reports for Selenium tests?

I recently made the switch to using jest for testing my JavaScript project after encountering coverage issues with mocha and chai. While my unit tests are providing coverage data, my Selenium tests are not. I've tried various solutions found in outdat ...

Unable to utilize the fetch method in Node.js for sending the API request

I am currently using fetch to send a POST request and retrieve data from an API on the server side (using nextjs 13 + node 18). Interestingly, I can successfully retrieve the data using postman and axios, but not with fetch. Below is the snippet of code ...