Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongoose validate array of subdocuments

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,
  },
});
like image 843
nbon Avatar asked Jul 16 '26 08:07

nbon


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' }
like image 188
BenSower Avatar answered Jul 17 '26 23:07

BenSower