Javascript 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

在我的模式中,我正在执行许多异步、自定义验证。然而,验证的行为并不像我期望的那样即使承诺以“假”来解决问题,mongoose仍继续验证。根据,情况不应该如此

示例架构:

    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
,您可能会抛出错误。