【问题标题】:Mongoose async custom validation not working as expectedMongoose 异步自定义验证未按预期工作
【发布时间】:2020-12-26 05:33:49
【问题描述】:

在我的架构中,我正在执行大量异步自定义验证。但是,验证的行为与我预期的不同。 即使 promise 解析为“false”,mongoose 仍会继续验证。根据their documentation,情况不应该如此。

示例架构:

    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.`,
        },
      },
    })

请注意,这两个架构字段的自定义验证异步发生。 questCategory 字段的验证工作得很好。如果 promise 解析为 false,则验证失败。但是,fulfillmentPeriod 字段并非如此。即使 promise 解析为 false,验证也会成功。

我不确定为什么会出现这种奇怪的行为。如果我将fulfillmentPeriod 的验证重写为如下所示,那么一切都会再次按预期工作。解析为false 的承诺会导致验证失败。这是为什么?为什么它适用于下面的代码,但不适用于我上面粘贴的初始代码?那是因为我引用了另一个异步验证的架构字段吗?

validator: async function (v) {
  const result = await data_verificator.checkFulfillmentPeriod(this.questCategory, v);
  return result;
},

以防万一这很重要,checkFulfillmentPeriod 函数如下所示:

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函数看起来完全一样,只是查询设置不同。

我在这个问题上花了几个小时,现在我只是看不到任何错误。

如果能得到任何帮助/建议,我将不胜感激!

【问题讨论】:

  • 验证触发时this.questCategory的内容是什么?
  • @raven 它是 MongoDB ObjectID。我在 checkFulfillmentPeriod 函数中使用了一个 console.log() 来测试它。
  • 您是否尝试在此行添加返回? await data_verificator.checkFulfillmentPeriod(this.questCategory, v);
  • @raven yes :) 如果我写 return data_verificator.checkFulfillmentPeriod(this.questCategory, v) 一切正常。应该是这样写的吗?他们的文档说明如下:如果您的验证器函数返回一个承诺(如异步函数),猫鼬将等待该承诺解决 - 这意味着我应该只返回未解决的承诺为猫鼬会自动等待它解决吗?
  • 问题是,如果你不写 return 就像你在返回一个 Promise

标签: javascript node.js mongodb mongoose mongoose-schema


【解决方案1】:

您的验证器缺少 return 语句,因此就像您返回 Promise<void> 一样,这不会触发 mongo 的验证。您可以添加 return 或重写您的函数,并承诺后者不那么优雅。

new Promise( (resolve,reject) => {
  .....
  resolve(true/false);
});

【讨论】:

    【解决方案2】:

    你能试试这个代码吗:

    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.`,
            },
          },
        })
    

    【讨论】:

    • 感谢您的回复。但是为什么在 questCategory 的情况下等待没有返回工作?
    • 如果没有返回语句,它将返回 void。它永远不会是错误的,它将始终被视为真实的陈述
    • 你能不能把checkIfQuestCategoryExists分享给return false,你可能会报错。
    猜你喜欢
    • 2011-08-16
    • 1970-01-01
    • 2012-11-14
    • 1970-01-01
    • 2011-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多