title: MongooseJS modify document during pre hook
body: <p>I'm having some issues with mongoose. My goal is that during pre-save, I would be able to modify the object, doing things like splitting the tags if needed, or in another case calculating the summation of a sub-document durations and update it within the main document.</p>
  
  <p>What I'm finding is that if I load a model, then call doc.update passing the new data, only <code>schema.pre('update', ...)</code> triggers, and any changes to <code>this</code> within my middleware are not updated. I also tried using <code>this.set('...', ....);</code> within my update middleware to no avail.</p>
  
  <p>It seems if I do <code>doc.save(...)</code> instead, then changes to <code>this</code> within <code>schema.pre('save', ...)</code> are appended as expected. Aside from extending the posted variables into my model's properties and saving, I'm not seeing any way of leveraging doc.update for this purpose.</p>
  
  <p>My Goals:
  - Update an existing document via <code>doc.update(properties, ....)</code>
  - Use middleware during saving to modify the document, do advanced validation, and update related documents
  - Use middleware during updating to modify the document, do advanced validation, and update related documents
  - Interchangeably use model.findByIdAndUpdate, model.save, model.findById->doc.update, model.findById->doc.save and all tap into my save/update middleware.</p>
  
  <p>Some arbitrary sample code:</p>
  
  <pre><code>function loadLocation(c) {
      var self = this;
      c.Location.findById(c.params.id, function(err, location) {
          c.respondTo(function(format) {
              if (err | !location) {
                  format.json(function() {
                      c.send(err ? {
                          code: 500,
                          error: err
                      } : {
                          code: 404,
                          error: 'Location Not Found!'
                      });
                  });
                  format.html(function() {
                      c.redirect(c.path_to.admin_locations);
                  });
              } else {
                  self.location = location;
                  c.next();
              }
          });
      });
  }
  
  LocationController.prototype.update = function update(c) {
      var location = this.location;
      this.title = 'Edit Location Details';
  
      location.update(c.body.Location, function(err) {
          c.respondTo(function(format) {
              format.json(function() {
                  c.send(err ? {
                      code: 500,
                      error: location &amp;&amp; location.errors || err
                  } : {
                      code: 200,
                      location: location.toObject()
                  });
              });
              format.html(function() {
                  if (err) {
                      c.flash('error', JSON.stringify(err));
                  } else {
                      c.flash('info', 'Location updated');
                  }
                  c.redirect(c.path_to.admin_location(location.id));
              });
          });
      });
  };
  
  module.exports = function(compound) {
      var schema = mongoose.Schema({
          name: String,
          address: String,
          tags: [{ type: String, index: true }],
          geo: {
              type: {
                  type: String,
              default:
                  "Point"
              },
              coordinates: [Number] // Longitude, Latitude
          }
      });
      schema.index({
          geo: '2dsphere'
      });
      var Location = mongoose.model('Location', schema);
      Location.modelName = 'Location';
      compound.models.Location = Location;
  
      schema.pre('save', function(next) {
          if(typeof this.tags === 'string') {
              this.tags = this.tags.split(',');
          }
      });
  };
  </code></pre>
  
  <p>==== <strong>* revised sample *</strong> ====</p>
  
  <pre><code>module.exports = function(compound) {
      var schema = mongoose.Schema({
          name: String,
          bio: String
      });
  
      schema.pre('save', function(next) {
          console.log('Saving...');
          this.bio = "Tristique sed magna tortor?"; 
          next();
      });
  
      schema.pre('update', function(next) {
          console.log('Updating...');
          this.bio = "Quis ac, aenean egestas?"; 
          next();
      });
  
      var Author = mongoose.model('Author', schema);
      Author.modelName = 'Author';
      compound.models.Location = Author;
  };
  </code></pre>