gpt4 book ai didi

javascript - Mongoose 无限循环模型创建

转载 作者:可可西里 更新时间:2023-11-01 10:41:03 30 4
gpt4 key购买 nike

背景

我有关于调查的 Mongoose Schema,它需要检查调查是否属于另一个集合中的一组国家/地区。

代码

为了检查这一点,我有一个 surveySchema、一个 countrySchema 和一个我在其中创建模型并连接到数据库的文件。

要执行调查是否属于有效国家/地区的检查,我使用 Mongoose async validators在 surveySchema 中,如下所示:

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 文件。因为这个文件还负责连接DB,所以我决定把它做成Singleton。这样,我应该只连接一次,所有进一步的请求将始终返回相同的模型,这将是理想的。

问题

这里的问题是我有一个循环依赖导致:

RangeError: Maximum call stack size exceeded at exports.isMongooseObject (/home/ubuntu/workspace/server/node_modules/mongoose/lib/utils.js:537:12)

...

导致这个错误的代码流程是:

  1. 代码运行 getModels()`
  2. getModels() 检查 models 是否未定义并运行 initialize()
  3. initialize() 尝试创建模型。
  4. 在创建调查模型时 Survey: mongoose.model('Survey', require("./surveySchema.js")) 它会遇到 validator 函数,这又需要 models.js
  5. 无限循环开始

问题

  1. 有没有其他方法可以在不进行异步验证的情况下检查调查的国家/地区是否属于该县的集合?
  2. 我如何构建/更改我的代码以防止这种情况发生?

最佳答案

如评论中所述,我认为您对如何使用 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 中运行一次匿名函数,所以我会 invoke it immediately并将模块的导出设置为其结果:

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();

至于验证选项,如果正常的异步验证不能为您使用 the docs 中描述的串行或并行机制添加您自己的中间件验证代码,您没有理由不这样做。 .

评论后更新

您指出的第二个问题是,在第一次执行 getModels() -> initialize() 期间,您调用了 require('./surveySchema.js') , 但是这个调用 getModels() 仍然在被调用的过程中并且还没有初始化 models, 所以 initialize() 是重新输入。

我认为您要实现的目标很好(调查架构 取决于客户模型),因为您仍然可以在没有任何循环依赖的情况下绘制对象图,这就是你实现它的方式,你最终得到了一个。我认为处理这个问题的最简单方法实际上是保留循环引用,但推迟在 surveySchema.js 中调用 getModels() 的时间点:

"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;

不过,一种更简洁且可能更可扩展的方法可能是将连接代码与模型代码分开,因为这完全是一个不同的概念。

在更多评论后更新#2

您看到的无限堆栈是因为您没有正确使用 API。你有:

const surveySchema = {
country: {
validate: {
validator: {
isAsync: true,
validator: async function(val, callback) {...}
},
},
...
}
};

你应该:

const surveySchema = {
country: {
validate: {
isAsync: true,
validator: async function(val, callback) {...}
},
...
}
};

根据 the docs .

关于javascript - Mongoose 无限循环模型创建,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43292218/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com