SankaD SankaD - 5 months ago 8
Node.js Question

Is there a way to define 'required' keys conditionally in a schema?

Is there a way to conditionally set the 'required' field in a mongoose schema? .

Example :

if x==true, y's required=true. else y's required=false

Answer

Sure you can, using mongoose's middleware. If you require some form of custom validation then you can just wire that into the hooks that are available. General validation takes place "pre save", so there is a good place to put the hook.

As a full example:

var async = require('async'),
    mongoose = require('mongoose'),
    Schema = mongoose.Schema;

mongoose.connect('mongodb://localhost/test');

var testSchema = new Schema({
  x: Number,
  y: Number
});

testSchema.pre('save', function(next) {
  if ( this.x && !this.y ) {
    return next(new Error("y is required when x is set"));
  }
  next();
});

var Test = mongoose.model("Test", testSchema, "test");

async.series(
  [
    function(callback) {
      var test = new Test({ y: 1 });
      test.save(function(err,test) {
        if (err) {
          console.log( err );
        } else {
          console.log("test1: ok");
        }
        console.log( "y only expected to work");
        callback();
      });
    },
    function(callback) {
      var test = new Test({ x: 1 });
      test.save(function(err,test) {
        if (err) {
          console.log( err );
        } else {
          console.log("test2: ok");
        }
        console.log("x only expected to fail");
        callback();
      });
    },
    function(callback) {
      var test = new Test({ x: 1, y: 1});
      test.save(function(err,test) {
        if (err) {
          console.log( err );
        } else {
          console.log("test3: ok");
        }
        console.log("x and y is fine");
        callback();
      });
    }
  ]
);

So the hook that was placed on the schema definition can inspect the contents of the fields passed in and determine whether or not those meet the rules you have defined. In this case you are looking for the value of "y" to be present always when "x" is defined. That means "y" by itself is fine and "x" and "y" together meet the rule, but "y" by itself without "x" will produce an error.

See middleware in the documentation for more detail as well as validation for actually validating the values given for a field.