Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to create a multi-select enum in mongoose

I have a model with an enum field, and currently documents can have any single value from the enum. I want documents to be allowed to have an array of values, but have mongoose enforce that all of the values are valid options that exist in the enum - is that possible?

Essentially I want the equivalent of a HTML <select multiple> element instead of a <select>

like image 776
Nathan Friedly Avatar asked Dec 12 '14 16:12

Nathan Friedly


2 Answers

Yes, you can apply an enum to a path that's defined as an array of strings. Each value will be passed to the enum validator and will be checked to ensure they are contained within the enum list.

var UserSchema = new Schema({
    //...
    pets: {type: [String], enum: ["Cat", "Dog", "Bird", "Snake"]}
    //...
});

//... more code to register the model with mongoose

Assuming you have a multi-select in your HTML form with the name pets, you could populate the document from the form post, within your route, like this:

var User = mongoose.model('User');
var user = new User();

//make sure a value was passed from the form
if (req.body.pets) {
    //If only one value is passed it won't be an array, so you need to create one
    user.pets = Array.isArray(req.body.pets) ? req.body.pets : [req.body.pets]; 
}
like image 173
Brian Shamblen Avatar answered Oct 09 '22 17:10

Brian Shamblen


For reference, on Mongoose version 4.11 the enum restriction on the previous accepted answer does not work, but the following does work:

const UserSchema = new Schema({
  //...
  role: [ { type: String, enum: ["admin", "basic", "super"] } ]
  //...
})

Or, if you want/need to include things other than type:

const UserSchema = new Schema({
  //...
  role: {
    type: [ { type: String, enum: ["admin", "basic", "super"] } ],
    required: true
  }
  //...
})
like image 35
mlubs Avatar answered Oct 09 '22 19:10

mlubs