Javascript Mongoose异步自定义验证未按预期工作
在我的模式中,我正在执行许多异步、自定义验证。然而,验证的行为并不像我期望的那样即使承诺以“假”来解决问题,mongoose仍继续验证。根据,情况不应该如此 示例架构:Javascript Mongoose异步自定义验证未按预期工作,javascript,node.js,mongodb,mongoose,mongoose-schema,Javascript,Node.js,Mongodb,Mongoose,Mongoose Schema,在我的模式中,我正在执行许多异步、自定义验证。然而,验证的行为并不像我期望的那样即使承诺以“假”来解决问题,mongoose仍继续验证。根据,情况不应该如此 示例架构: var questSchema = mongoose.Schema({ questCategory: { type: mongoose.Schema.Types.ObjectId, required: true, validate: { va
var questSchema = mongoose.Schema({
questCategory: {
type: mongoose.Schema.Types.ObjectId,
required: true,
validate: {
validator: async function (v) {
await data_verificator.checkIfQuestCategoryExists(v);
},
message: (props) => `${props.value} is not a valid quest category id.`,
},
},
fulfillmentPeriod: {
type: String,
required: true,
validate: {
validator: async function (v) {
await data_verificator.checkFulfillmentPeriod(this.questCategory, v);
},
message: (props) =>
`${props.value} is an invalid value as it violates the limitations set by the quest category.`,
},
},
})
const checkFulfillmentPeriod = async function (categoryId, period) {
const connectionManager = require("../configuration").connectionManager;
var category = await connectionManager.QuestCategoryModel.findOne({
_id: categoryId,
availableFulfillmentPeriods: {
$elemMatch: {
period: period,
},
},
});
if (!category) return false;
return true;
};
请注意,对于这两个架构字段,自定义验证是异步进行的。questCategory
字段的验证非常有效。如果承诺解析为false
,则验证失败。但是,fulfillmentPeriod
字段的情况并非如此。即使承诺解析为false
,验证也会成功
我不知道为什么我会有这种奇怪的行为。如果我将fulfillmentPeriod
的验证重写为如下所示,那么一切都会再次按预期工作。承诺解析为false
会导致验证失败。为什么呢?为什么它可以使用下面的代码,而不能使用上面粘贴的初始代码?这是因为我正在引用另一个异步验证的模式字段吗
validator: async function (v) {
const result = await data_verificator.checkFulfillmentPeriod(this.questCategory, v);
return result;
},
如果这很重要,checkFulfillmentPeriod
函数如下所示:
var questSchema = mongoose.Schema({
questCategory: {
type: mongoose.Schema.Types.ObjectId,
required: true,
validate: {
validator: async function (v) {
await data_verificator.checkIfQuestCategoryExists(v);
},
message: (props) => `${props.value} is not a valid quest category id.`,
},
},
fulfillmentPeriod: {
type: String,
required: true,
validate: {
validator: async function (v) {
await data_verificator.checkFulfillmentPeriod(this.questCategory, v);
},
message: (props) =>
`${props.value} is an invalid value as it violates the limitations set by the quest category.`,
},
},
})
const checkFulfillmentPeriod = async function (categoryId, period) {
const connectionManager = require("../configuration").connectionManager;
var category = await connectionManager.QuestCategoryModel.findOne({
_id: categoryId,
availableFulfillmentPeriods: {
$elemMatch: {
period: period,
},
},
});
if (!category) return false;
return true;
};
该函数只检查是否存在与条件匹配的类别。如果是,则返回true。否则就错了。据我所知,这个问题并不是源于这个函数,而是与mongoose的验证有关
checkIfQuestCategoryExists函数看起来完全相同,只是查询设置不同。
我在这个问题上花了几个小时,现在我再也看不到任何错误了
如果能得到任何帮助/建议,我将不胜感激您的验证器缺少return语句,因此就像您返回了一个
承诺
,这不会触发mongo的验证。您可以添加return,也可以重写函数,并承诺后者不那么优雅
new Promise( (resolve,reject) => {
.....
resolve(true/false);
});
您可以尝试以下代码:
var questSchema = mongoose.Schema({
questCategory: {
type: mongoose.Schema.Types.ObjectId,
required: true,
validate: {
validator: async function (v) {
return await data_verificator.checkIfQuestCategoryExists(v);
},
message: (props) => `${props.value} is not a valid quest category id.`,
},
},
fulfillmentPeriod: {
type: String,
required: true,
validate: {
validator: async function (v) {
return await data_verificator.checkFulfillmentPeriod(this.questCategory, v);
},
message: (props) =>
`${props.value} is an invalid value as it violates the limitations set by the quest category.`,
},
},
})
触发验证时,
this.questCategory
的内容是什么?@raven这是MongoDB对象ID。我在checkFulfillmentPeriod函数中使用了一个console.log()来测试它。您是否尝试在这行中添加一个返回<代码>等待数据\u验证器。检查完成期(this.questCategory,v)@raven yes:)如果我写返回数据\u验证器。checkFulfillmentPeriod(this.questCategory,v)
一切正常。应该是这样写的吗?他们的文档说明如下:如果验证器函数返回承诺(如异步函数),mongoose会等待承诺的解决-这意味着我应该只返回未解决的承诺,因为mongoose会自动等待它解决?问题是,如果你不写回报,就好像你在返回承诺感谢你的回复。但是为什么在questCategory的情况下没有返回的Wait有效?如果没有返回语句,它将返回void。它永远不会为false,并且将始终视为true语句。您是否可以共享checkIfQuestCategoryExists
,而不是返回false
,您可能会抛出错误。