23

I want to create a model layer with Mongoose for my user documents, which does:

  1. validation (unique, length)
  2. canonicalisation (username and email are converted to lowercase to check uniqueness)
  3. salt generation
  4. password hashing
  5. (logging)

All of these actions are required to be executed before persisting to the db. Fortunately mongoose supports validation, plugins and middleware.

The bad thing is that I cannot find any good material on the subject. The official docs on mongoosejs.com are too short...

Does anyone have an example about pre actions with Mongoose (or a complete plugin which does all, if it exists)?

Regards

Tas
  • 7,023
  • 3
  • 36
  • 51
dev.pus
  • 7,919
  • 13
  • 37
  • 51
  • I thought the documentation on mongoosejs.com was pretty clear in this area. What have you tried that isn't working? – JohnnyHK Jul 04 '12 at 13:36
  • the validation sector is clear but not how to prepare the object before some persistment. I think the Schema.pre('save', callback); function could be it but the full example is missing also I don't know how to access the attributes of the object in the pre function – dev.pus Jul 04 '12 at 14:03
  • You access the attributes of the document via `this` in your middleware function. – JohnnyHK Jul 04 '12 at 14:12
  • Could you copy this in an answer so I can mark the question answered :) – dev.pus Jul 04 '12 at 14:32

3 Answers3

35

In your Schema.pre('save', callback) function, this is the document being saved, and modifications made to it before calling next() alter what's saved.

JohnnyHK
  • 305,182
  • 66
  • 621
  • 471
30

Another option is to use Getters. Here's an example from the website:

function toLower (v) {
  return v.toLowerCase();
}

var UserSchema = new Schema({
  email: { type: String, set: toLower } 
});

https://mongoosejs.com/docs/tutorials/getters-setters.html

Thilina Ashen Gamage
  • 1,367
  • 1
  • 12
  • 21
bento
  • 4,846
  • 8
  • 41
  • 59
  • 2
    It's worth noting that this is the only option if the value that you're passing is not the same type that is defined in the schema for the specified property. E. g. You have an `amount` property that is of type `number` but the value that you pass in for processing is a `string`. – Don May 23 '17 at 19:19
17
var db = require('mongoose');
var schema = new db.Schema({
  foo:     { type: String }
});

schema.pre('save', function(next) {
  this.foo = 'bar';

  next();
});

db.model('Thing', schema);
Rich Apodaca
  • 28,316
  • 16
  • 103
  • 129
  • it could be noted, that pre for 'save' does not fire on update. use 'update' instead – sasha Oct 11 '16 at 21:28
  • @sasha can you explain what you mean – Dipanshu Mahla Apr 14 '21 at 18:05
  • @DipanshuMahla It's been a bit and I'm currently not to deep into mongoose tbh, but what I meant was probably that the schema.pre('save') function does not fire (or doesn't get executed), when data gets updated. It might only fire when new data is inserted. So when you want to have updates covered via schema.pre(), you should use 'update' – sasha May 04 '21 at 21:21