Search code examples
mongodbvalidationmongodb-querynosqlmongodb-schema

How to specify that at least one field is required out of three in total?


In my MongoDB model, there are 3 fields in total. Any document added to this collection must contain at least 1 of those 3 fields.

How can this be specified in the validation staged?


Solution

  • You can enum validation constraint which collection creation as below:

    db.createCollection("jobs", {
       validator: {
          $jsonSchema: {
             bsonType: "object",
             required: [ "status" ],
             properties: {
                status: {
                   enum: [ "Done", "Failed", "Initial" ],
                   description: "can only be one of the enum values and is required"
                },
             }
          }
       }
    })
    

    From the docs

    Mongoose has several inbuilt validators. Strings have enum as one of the validators. So enum creates a validator and checks if the value is given in an array. E.g:

    var userSchema = new mongooseSchema({
       status: {
            type: String,
            enum : ['Done','Failed', 'Initial'],
            default: 'Initial'
        },
    })
    

    You can use custom validator to check if we have one of 3 keys in the object

    const testSchema = mongoose.Schema({
      field1: {
        type: String,
        validate: {
          validator: function(v) {
            if (this.field2 == undefined && this.field3 == undefined) {
              return true;
            }
            return false;
          },
        },
      },
      field2: {
        type: String,
        validate: {
          validator: function(v) {
            if (this.field1 == undefined && this.field3 == undefined) {
              return true;
            }
            return false;
          },
        },
      },
      field3: {
        type: String,
        validate: {
          validator: function(v) {
            if (this.field2 == undefined && this.field1 == undefined) {
              return true;
            }
            return false;
          },
        },
      },
    });