我有关于调查的Mongoose Schema,需要检查调查是否属于另一个集合中的一组国家。
要检查这一点,我有一个surveySchema,countrySchema和一个文件,我在其中创建模型并连接到数据库。
要执行调查属于有效国家/地区的检查,我在surveySchema中使用Mongoose async validators,如下所示:
surveySchema.js:
"use strict";
const mongoose = require("mongoose");
const surveySchema = {
subject: { type: String, required: true },
country: {
type: String,
validate: {
validator: {
isAsync: true,
validator: async function(val, callback) {
const {
Country
} = require("./models.js").getModels();
const countriesNum = await Country.find({"isoCodes.alpha2": val}).count();
callback(countriesNum === 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 = () => {
//Connect to DB
const {
dbConnectionURL
} = JSON.parse(fs.readFileSync(DB_CONFIG, "utf8"));
mongoose.connect(dbConnectionURL);
mongoose.Promise = global.Promise;
//Build Models Object
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
});
}());
这里的想法是我在其他地方使用 models.js 文件。因为这个文件也负责连接数据库,所以我决定把它变成一个Singleton。这样,我应该只连接一次,所有进一步的请求将始终返回相同的模型,这将是理想的。
这里的问题是我有一个循环依赖,导致:
RangeError: Maximum call stack size exceeded at exports.isMongooseObject (/home/ubuntu/workspace/server/node_modules/mongoose/lib/utils.js:537:12)
...
导致此错误的代码流程为:
getModels()
检查models
是否未定义并运行initialize()
initialize()
尝试创建模型。 Survey: mongoose.model('Survey', require("./surveySchema.js"))
时,它会遇到validator
函数,这又需要models.js
答案 0 :(得分:1)
如评论中所述,我认为您对如何使用models.js模块感到有些困惑。我认为这就是发生的事情:
您正在从models.js导出单个函数:
<强> models.js 强>
module.exports = function() { ... };
因此,当您需要它时,您只需获得该功能:
<强> surveySchema.js 强>
const models = require("./models.js");
models
现在是一个功能。这意味着每次调用它时,都会遍历models.js中的代码并创建一个新变量let models;
,以及新函数initialize()
和getModels()
。
你可以将let models
移出匿名函数进入可能修复它的全局范围,但是为了我的钱,你只想在models.js中运行一次匿名函数,所以我会{{ 3}}并将模块的导出设置为其结果:
<强> models.js 强>
module.exports = (function() {
// codez here
return Object.freeze({
getModels
});
})(); // immediately invoke the function.
使用它:
// models is now the frozen object returned
const { Survey } = models.getModels();
至于验证的选项,如果正常的异步验证没有为您使用串行或并行机制,您没有理由不添加自己的中间件验证代码,如invoke it immediately
您指出的第二个问题是,在第一次执行getModels() -> initialize()
时,您调用了require('./surveySchema.js')
,但这会调用getModels()
,而models
仍然处于被调用过程中并且还没有被调用; t尚未初始化initialize()
,因此重新输入getModels()
。
我认为您尝试实现的目标很好(调查架构取决于客户模型),因为您仍然可以在没有任何循环的情况下绘制对象图依赖性,它只是你实现它的方式,你最终得到了它。我认为最简单的处理方法是保留循环引用,但推迟在surveySchema.js
中调用"use strict";
const mongoose = require("mongoose");
const models = require("./models.js");
const surveySchema = {
subject: { type: String, required: true },
country: {
type: String,
validate: {
validator: {
isAsync: true,
validator: async function(val, callback) {
// !! moved from the global scope to here, where we actually use it
const {
Country
} = models.getModels();
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;
的点:
const surveySchema = {
country: {
validate: {
validator: {
isAsync: true,
validator: async function(val, callback) {...}
},
},
...
}
};
但是,更简洁,可能更具可扩展性的方法可能是将连接代码与模型代码分开,因为它完全是一个不同的概念。
您看到的无限堆栈是因为您没有正确使用API。你有:
const surveySchema = {
country: {
validate: {
isAsync: true,
validator: async function(val, callback) {...}
},
...
}
};
你应该:
char c = i + 'A';
index = hashFunction(&c) % size;
根据the docs。