Monday, 14 September 2020

Mongoose async custom validation not working as expected

in my schema, I'm performing a lot of asynchronous, custom validations. However, validation is not behaving as I expect it to behave. Even though promises resolve with "false", mongoose continues validation. According to their documentation, that shouldn't be the case.

Sample schema:

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

Note that the custom validation happens asynchronously for those two schema fields. The validation of the questCategory field works perfectly fine. If the promise resolves to false, validation fails. However, that's not the case for the fulfillmentPeriod field. Even though the promise resolves to false, the validation succeeds.

I am not sure why I get this weird behavior. If I were to rewrite validation of the fulfillmentPeriod to look like the following, everything works as expected again. The promise resolving to false causes the validation to fail. Why is that? Why does it work with below code but not with the initial code I pasted above? Is that because I'm referencing another schema field that is validated asynchronously?

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

Just in case this is important, the checkFulfillmentPeriod function looks like this:

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

The function simply checks if there's a category matching the criteria. If so, true is returned. Otherwise false. From what I've found out, the issue doesn't originate in this function but has something to do with mongoose's validation.

The checkIfQuestCategoryExistsfunction looks exactly the same, just with different query settings.

I've spent hours on this issue and at this point I just don't see any errors anymore.

I would appreciate any help/advice I could get!



from Mongoose async custom validation not working as expected

No comments:

Post a Comment