Mongoose validate array of subdocuments

Viewed 1942

I have the following schema

const TextSchema = new Schema({
  locale: String,
  contexts: [{
    field: String,
    channel: String,
  }],
});

I would like to add a validation to each context that ensures that either field or channel is set.

I have tried extracting the context to a separate schema and setting the validation like below but it only validates the whole array instead of each context.

const TextSchema = new Schema({
  locale: String,
  contexts: {
    type: [ContextSchema],
    validate: validateContext,
  },
});
1 Answers

I believe you can't define a validator for a properly typed object in an array, but only on fields. If there is a way to do this as expected, I'd be glad to retract my answer!

However:

You CAN define a validator on a field and access the object it was in like this:

const validator = function(theField) {
    console.log('The array field', theField);
    console.log('The array object', this);
    return true;
};

const TextSchema = new Schema({
    locale: String,
    contexts: [{
      field: {
        type: String,
        validate: validator
      },
      channel: {
        type: String,
        validate: validator,
      },
    }],
});

Prints something like

The array field FIELDVALUE
The array object { _id: 5c34a4172a0f34220d17fc1f, field: '21', channel: '2123' }

This has the disadvantage that the validator runs on every field in the array. If you only set them at the same time, you could however only set it for one field.

Alternatively: If you don't need to define the types of the objects in an array however, you can just set the type of the array objects to Mixed and define a validator on this field.

 const TextSchema = new Schema({
    locale: String,
    contexts: [{
      type: mongoose.SchemaTypes.Mixed, 
      validate : function (val) {
       console.log(val);
       return true;
      },
    }],
});

Should also print

{ _id: 5c34a4172a0f34220d17fc1f, field: '21', channel: '2123' }
Related