Mongoose difference between .save() and using update()

To modify a field in an existing entry in mongoose, what is the difference between using

model = new Model([...])
model.field = 'new value';
model.save();

and this

Model.update({[...]}, {$set: {field: 'new value'});

The reason I'm asking this question is because of someone's suggestion to an issue I posted yesterday: NodeJS and Mongo - Unexpected behaviors when multiple users send requests simultaneously. The person suggested to use update instead of save, and I'm not yet completely sure why it would make a difference.

Thanks!

Answers


Two concepts first. Your application is the Client, Mongodb is the Server.

The main difference is that with .save() you already have an object in your client side code or had to retrieve the data from the server before you are writing it back, and you are writing back the whole thing.

On the other hand .update() does not require the data to be loaded to the client from the server. All of the interaction happens server side without retrieving to the client.So .update() can be very efficient in this way when you are adding content to existing documents.

In addition, there is the multi parameter to .update() that allows the actions to be performed on more than one document that matches the query condition.

There are some things in convenience methods that you loose when using .update() as a call, but the benefits for certain operations is the "trade-off" you have to bear. For more information on this, and the options available, see the documentation.

In short .save() is a client side interface, .update() is server side.


Some differences:

  • As noted elsewhere, update is more efficient than find followed by save because it avoids loading the whole document.
  • A Mongoose update translates into a MongoDB update but a Mongoose save is converted into either a MongoDB insert (for a new document) or an update.
  • It's important to note that on save, Mongoose internally diffs the document and only sends the fields that have actually changed. This is good for atomicity.
  • By default validation is not run on update but it can be enabled.
  • The middleware API (pre and post hooks) is different.

There is a useful feature on Mongoose called Middleware. There are 'pre' and 'post' middleware. The middlewares get executed when you do a 'save', but not during 'update'. For example, if you want to hash a password in the User schema everytime the password is modified, you can use the pre to do it as follows. Another useful example is to set the lastModified for each document. The documentation can be found at http://mongoosejs.com/docs/middleware.html

UserSchema.pre('save', function(next) {
var user = this;
// only hash the password if it has been modified (or is new)
if (!user.isModified('password')) {
    console.log('password not modified');
    return next();
}
console.log('password modified');
// generate a salt
bcrypt.genSalt(10, function(err, salt) {
    if (err) {
        return next(err);
    }

    // hash the password along with our new salt
    bcrypt.hash(user.password, salt, function(err, hash) {
        if (err) {
            return next(err);
        }
        // override the cleartext password with the hashed one
        user.password = hash;
        next();
    });
});
});

Need Your Help

Caused by: java.lang.IllegalStateException: Multiple outgoing edges with label: "StreamEntry" for vertex: test2/document1

java neo4j cluster-computing graph-databases

We have a 3 node neo4j cluster where two nodes acting as front ends are embedded neo4j instances in java with a restlet front end for getting and posting to our graph db. The 3rd instance is neo4j-

List inside detail card of Ext.NestedList

sencha-touch-2

my application receives data from the database.