Background
I have Mongoose Schema about Surveys, that needs to check if the Survey belongs to a set of countries that is in another collection.
Code
To check this, I have a surveySchema, a countrySchema, and a file where I create the models and connect to the DB.
To perform the check that a survey belongs to a valid country, I am using Mongoose async validators in surveySchema like the following:
surveySchema.js:
"use strict";
const mongoose = require("mongoose");
const models = require("./models.js");
const {
Country
} = models().getModels();
const surveySchema = {
subject: { type: String, required: true },
country: {
type: String,
validate: {
validator: {
isAsync: true,
validator: async function(val, callback) {
const countries = await Country.find({"isoCodes.alpha2": val});
callback(countries.length === 1);
}
},
message: "The country {VALUE} is not available in the DB at the moment."
}
}
};
module.exports = new mongoose.Schema(surveySchema);
module.exports.surveySchema = surveySchema;
countrySchema.js:
"use strict";
const mongoose = require("mongoose");
const countrySchema = {
name: { type: String, required: true },
isoCodes:{
alpha2: { type: String, required: true }
}
}
};
module.exports = new mongoose.Schema(countrySchema);
module.exports.countrySchema = countrySchema;
models.js:
"use strict";
const mongoose = require("mongoose");
const fs = require("fs");
const DB_CONFIG = "./config/dbConfig.json";
/**
* Module responsible for initializing the Models. Should be a Singleton.
*/
module.exports = function() {
let models;
const initialize = () => {
const {
dbConnectionURL
} = JSON.parse(fs.readFileSync(DB_CONFIG, "utf8"));
mongoose.connect(dbConnectionURL);
mongoose.Promise = global.Promise;
models = {
Country: mongoose.model('Country', require("./countrySchema.js")),
Survey: mongoose.model('Survey', require("./surveySchema.js"))
};
};
const getModels = () => {
if (models === undefined)
initialize();
return models;
};
return Object.freeze({
getModels
});
};
The idea here is that I am using the models.js file in other places as well. Because this file is also responsible for connecting to the DB, I decided to make it a Singleton. This way, I should only connect once, and all further requests will always return the same Models, which would be ideal.
Problem
The problem here, is that every time I run something like:
const {
Survey
} = models().getModels();
The code tries to connect to the DB and tries to re-initialize the models again. The Singleton, is not a Singleton at all.
This is mostly visible in my api.js files, where I also use the models.js file.
Consequently, every time I launch the MEAN app I have, I have two types of critical errors:
- Tried to connect to a DB whose connection is still active
- Tried to instantiate models when they were already instantiated.
This whole thing happens because every time I call models()
, the variable models
is undefined
, and so I run the initialize
function again ...
Questions
- Is there any other way to check if a Survey's country is part of the county's collection without making a async validation?
- How can I structure/change my code so this doesn't happen?
via Flame_Phoenix
No comments:
Post a Comment