My requirements are that I want to create schemas dynamically from a user given form. I am able to create them and they work perfectly fine but only as long as my server is up. As soon as it goes down I get the error that the schemas are not registered, but they keep showing up on MongoDB compass. So, essentially the models exist only on the connection instance but they dont get saved inside the database
I am using nodejs, express and mongoose with MongoDB to create a templated sort of e-commerce platform. I am trying to dynamically create models through post requests using my API. I use a single instance of mongoose connection to create these models.
const config = require('config');
const mongoose = require('mongoose');
const logger = require('../logger/logger.js');
async function runDB() {
const db = await mongoose.connect(config.get('database.mongodb.uri'));
logger.info('Connected to MongoDB');
return db;
}
module.exports = {
runDB,
mongoose,
};
I then use this mongo instance throughout my controllers. I can post my data and it shows up on MongoDB Compass, but when if my server stops the data is not retained and yet when I try to create the model again it says that the model already exists. Here’s an example controller function:
const postCategory = async function (req, res) {
req.body.name = standardizeInput(req.body.name);
const categoryExists = await CategoryModel.findOne({ name: req.body.name });
if (categoryExists) {
return res
.status(statusCodes.StatusCodes.FORBIDDEN)
.json({ status: false, message: 'Category already exists', data: null });
}
const category = new CategoryModel({
name: req.body.name,
description: req.body.description,
isDeleted: req.body.isDeleted,
});
if (mongoose.model[req.body.name]) {
return res
.status(statusCodes.StatusCodes.FORBIDDEN)
.json({ status: false, message: 'Model already exists', data: null });
}
if (Object.keys(req.body.description) === 0)
return res
.status(statusCodes.StatusCodes.BAD_REQUEST)
.json({ status: false, message: 'Description is empty', data: null });
const newModelForCategory = await createCategoryModel(req);
category.save().then((result) => {
const data = _.pick(result, pickProps);
res
.status(statusCodes.StatusCodes.CREATED)
.json({
status: true,
message: 'Category added and model created successfully',
result: { data },
});
});
};
const createCategoryModel = async function (req) {
const { name, description } = req.body;
let categorySchema = new mongoose.Schema({});
Object.keys(description).forEach((field) => {
const fieldConfig = description[field];
categorySchema.add({
[field]: {
type:
fieldConfig.type == 'boolean'
? Boolean
: fieldConfig.type == 'number'
? Number
: fieldConfig.type == 'string'
? String
: Mixed,
required: fieldConfig.required ? true : false,
min: fieldConfig.min ? fieldConfig.min : 0,
max: fieldConfig.max ? fieldConfig.max : 512,
},
});
});
categorySchema.add({ isDeleted: { type: Boolean, default: false } });
const newModelForCategory = mongoose.model(name, categorySchema);
return newModelForCategory;
};
I cant find a way where I can retain the data in the db. Here’s the error I see after I try to add another product to the same category:
MissingSchemaError: Schema hasn't been registered for model "laptops".
Use mongoose.model(name, schema)
at Mongoose.model (C:\Users\semustax\Documents\Personal\compbus-portal\node_modules\mongoose\lib\mongoose.js:528:13)
at addCategoryFields (C:\Users\semustax\Documents\Personal\compbus-portal\controllers\product.js:59:55)
at newFn (C:\Users\semustax\Documents\Personal\compbus-portal\node_modules\express-async-errors\index.js:16:20)
at Layer.handle [as handle_request] (C:\Users\semustax\Documents\Personal\compbus-portal\node_modules\express\lib\router\layer.js:95:5)
at next (C:\Users\semustax\Documents\Personal\compbus-portal\node_modules\express\lib\router\route.js:144:13)
at body (C:\Users\semustax\Documents\Personal\compbus-portal\middleware\validate.js:17:3)
at C:\Users\semustax\Documents\Personal\compbus-portal\routes\Products.js:26:23
at newFn (C:\Users\semustax\Documents\Personal\compbus-portal\node_modules\express-async-errors\index.js:16:20)
at Layer.handle [as handle_request] (C:\Users\semustax\Documents\Personal\compbus-portal\node_modules\express\lib\router\layer.js:95:5)
at next (C:\Users\semustax\Documents\Personal\compbus-portal\node_modules\express\lib\router\route.js:144:13)