3

I am using mongoose with nodeJS. Consider the following schema:

var PersonSchema = new mongoose.Schema({
    "name": {type: String, default: "Human"},
    "age": {type: Number, defualt:20}
});
mongoose.model('Person', PersonSchema);

var order = new Order({
    name:null
});

This creates a new Person document with name set to null.

{
    name:null,
    age: 20
}

Is there anyway to check if the property being created/updated is null and if it is null set it back to default. The following declaration

var order = new Order();
order.name = null;
order.save(cb);

should create a new Person document with name set to default.

{
    name:"Human",
    age: 20
}

How would one implement this using NodeJs and mongoose.

3 Answers3

4

Well there are a few way to go about this:

PRE-SAVE/PRE-VALIDATE hooks

Mongoose Middleware hooks

Middleware (also called pre and post hooks) are functions which are passed control during execution of asynchronous functions.

PersonSchema.pre('save', function(next) {
    if (this.name === null) {
        this.name = 'Human';
    }

    next();
});

ENUM

Mongoose Validation and Mongoose Enums

Strings have enum, match, maxlength and minlength validators.

var PersonSchema = new mongoose.Schema({
    "name": {type: String, default: "Human", enum: ['Human', 'NONE-Human']},
    "age": {type: Number, defualt:20}
});

Update 1

If I have 20 fields where I want to check whether they are set to null, do I have to repeat this.field = default for all of them?

I guess you would have to.

What does NONE-Human in enums do? I could not find documentation for this online.

That is just an example of ENUM with enum you can only choose values that are specified in ENUM i.e. 'Name' can only have values of 'Human' or 'NONE-Human'.

Tim
  • 2,695
  • 3
  • 33
  • 39
  • Thank you! I have two quick follow up questions. 1. If I have 20 fields where I want to check whether they are set to null, do I have to repeat this.field = default for all of them? 2. What does NONE-Human in enums do? I could not find documentation for this online. – Neil Sanghrajka Jul 08 '16 at 18:37
  • @NeilSanghrajka Updated my answer with your questions. =) – Tim Jul 09 '16 at 00:59
  • @NeilSanghrajka If you find my help useful could you perhaps select my answer as accepted. Thanks – Tim Jul 10 '16 at 00:01
  • Nice. But see @Ralph's https://stackoverflow.com/a/42633419/9236556 that generalizes it quite nicely – daydreamer Jan 21 '22 at 21:56
4

A little late to answer this, but a more generic approach would be not to hardcode the fields again in the pre hook.

Instead let's use the schema itself to go over the fields and check for the fields that have default values and are explicitly set to null. In this case we set it to the default value.

PersonSchema.pre('save', function(next) {
  const self = this;
  Object.keys(this.schema.paths).forEach(function(key) {
    if(self.schema.paths[key].options.default && self[key] === null) {
      self[key] = self.schema.paths[key].options.default;
    }
  });
  next();
});
Ralph
  • 1,480
  • 11
  • 16
  • +1. The caveat seems to be that TypeScript doesn't like the "self[key]" notation. Just use "self.set(key, value)" and "self.get(key)" to attribute and get value, respectively. – daydreamer Jan 21 '22 at 21:54
2

An even later answer. I was looking for a simpler solution and came across this question. Thought I'd share what I ended up doing.

db.Person.create({
   name: usersName || "Human",
   age: usersAge,
})