maxko87
maxko87

Reputation: 2940

Make all fields required in Mongoose

Mongoose seems to default to make all fields not required. Is there any way to make all the fields required without changing each of:

Dimension = mongoose.Schema(
  name: String
  value: String
)

to

Dimension = mongoose.Schema(
  name:
    type: String
    required: true
  value: 
    type: String
    required: true
)

It'll get really ugly since I have a lot of these.

Upvotes: 20

Views: 32140

Answers (8)

Alp Durak
Alp Durak

Reputation: 25

I made this function for the complex types you may have so you don't have to declare a new variable for each type you have.

function require<T>(type: T): { type: T; required: true } {
  return {
    type,
    required: true,
  };
}

To use it you will just do this:

const mySchema = new mongoose.Schema({
  someRequiredField: require(String),
  someCustomTypedField: require(MyType),
});

It's much more cleaner and also more self explanatory this way.

Upvotes: 0

koga73
koga73

Reputation: 1022

Building on the previous answers, the module below will make fields required by default. The previous answers did not recurse nested objects/arrays.

Usage:

const rSchema = require("rschema");

var mySchema = new rSchema({
    request:{
        key:String,
        value:String
    },
    responses:[{
        key:String,
        value:String
    }]
});

Node module:

const Schema = require("mongoose").Schema;

//Extends Mongoose Schema to require all fields by default
module.exports = function(data){
    //Recursive
    var makeRequired = function(schema){
        for (var i in schema.paths) {
            var attribute = schema.paths[i];
            if (attribute.isRequired == undefined) {
                attribute.required(true);
            }
            if (attribute.schema){
                makeRequired(attribute.schema);
            }
        }
    };

    var schema = new Schema(data);
    makeRequired(schema);
    return schema;
};

Upvotes: 0

Flint
Flint

Reputation: 1711

All fields properties are in schema.paths[attribute] or schema.path(attribute);

One proper way to go : define when a field is NOT required,

Schema = mongoose.Schema;
var Myschema = new Schema({
    name : { type:String },
    type : { type:String, required:false }
})

and make them all required by default :

function AllFieldsRequiredByDefautlt(schema) {
    for (var i in schema.paths) {
        var attribute = schema.paths[i]
        if (attribute.isRequired == undefined) {
            attribute.required(true);
        }
    }
}

AllFieldsRequiredByDefautlt(Myschema)

The underscore way :

_=require('underscore')
_.each(_.keys(schema.paths), function (attr) {
    if (schema.path(attr).isRequired == undefined) {
        schema.path(attr).required(true);
    }
})

Test it :

MyTable = mongoose.model('Myschema', Myschema);
t = new MyTable()
t.save()

Upvotes: 9

maxko87
maxko87

Reputation: 2940

I ended up doing this:

r_string = 
  type: String
  required: true 

r_number = 
  type: Number
  required: true

and on for the other data types.

Upvotes: 12

chuyik
chuyik

Reputation: 1016

Mongoose didn't provide the method of setting all fields, but you could do it recursively.

Like Peter mentioned, you could pluginize it in order to reuse the code.

Recursively setting:

// game.model.js
var fields = require('./fields');
var Game = new Schema({ ... });

for(var p in Game.paths){
  Game.path(p).required(true);
}

Pluginized:

// fields.js
module.exports = function (schema, options) {
  if (options && options.required) {
    for(var p in schema.paths){
      schema.path(p).required(true);
    }
  }
}

// game.model.js
var fields = require('./fields');
var Game = new Schema({ ... });
Game.plugin(fields, { required: true });

Upvotes: 3

Andrew Drozdov
Andrew Drozdov

Reputation: 2183

You could do something like:

var schema = {
  name: { type: String},
  value: { type: String}
};

var requiredAttrs = ['name', 'value'];

for (attr in requiredAttrs) { schema[attr].required = true; }

var Dimension = mongoose.schema(schema);

or for all attrs (using underscore, which is awesome):

var schema = {
  name: { type: String},
  value: { type: String}
};

_.each(_.keys(schema), function (attr) { schema[attr].required = true; });

var Dimension = mongoose.schema(schema);

Upvotes: 12

Peter Lyons
Peter Lyons

Reputation: 146034

Well you could write a mongoose schema plugin function that walked the schema object and adjusted it to make each field required. Then you'd just need 1 line per schema: Dimension.plugin(allRequired).

Upvotes: 3

Samuel O&#39;Malley
Samuel O&#39;Malley

Reputation: 3551

I'm not sure if there's an easier way to do it in Mongoose, but I would do the following in your IDE/editor:

List out your fields as you would normally:

Dimension = mongoose.Schema(
  name: String
  value: String
)

Then do a find and replace on String and replace it with {type: String, required: true}, Giving you:

Dimension = mongoose.Schema(
  name: {type: String, required: true},
  value:  {type: String, required: true},
)

Then do the same for Number and other types.

Upvotes: 0

Related Questions