'How can .save give a "duplicate key error"?

I read that: .save checks if there is a document with the same _id as the one you save exists. When it exists, it replaces it. When no such document exists, it inserts the document as a new one.

But when I do this:

barTable = new barModel(received.bar);
return resolve(barTable.save());

It works great with new records but when saving an existing record I get this error:

{
    "err": true,
    "errMsg": "Error while barEdit: MongoError: E11000 duplicate key error collection: pattayanight.bar index: _id_ dup key: { : \"aa11\" }"
}

How come it does not just update like the documentation says?

This is my model:

var Schema      = mongoose.Schema;
var barSchema   = new Schema({
    _id:            String,
    type:           String,
    area:           String,
    shortText:      String 
}, { versionKey: false }); 
module.exports = mongoose.model('barModel', barSchema,'bar');

Of cause I can always use findOneAndUpdate with upsert:true but how come .save does not update an existing record?



Solution 1:[1]

Check out this answer, it might give you some light (Comments are also interesting):

Answer

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.

Solution 2:[2]

This appears to be caused by an optimization where if mongoid thinks it's a new document it will blindly insert the document.

It should work if you call (prior to saving):

barTable.new_record=(false)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Community
Solution 2 Adam C.