Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MongoError: cannot change _id of a document

I'm newbie to MongoDB and Backbone, so I try to understand them, but it is hard. I have a big, big problem: I cannot understand how to manipulate attributes in Backbone.Model to use in Views only what I need. More specific - I have a model:

window.User = Backbone.Model.extend({

    urlRoot:"/user",
    idAttribute: "_id",

    defaults: {
        _id: null,
        name: "",
        email: "[email protected]"
    }
});

window.UserCollection = Backbone.Collection.extend({
    model: User,

    url: "user/:id"
});

And I have a View:

beforeSave: function(){
    var self = this;
    var check = this.model.validateAll();
    if (check.isValid === false) {
        utils.displayValidationErrors(check.messages);
        return false;
    }
    this.saveUser();
    return false;
},

saveUser: function(){
    var self = this;
    console.log('before save');
    this.model.save(null, {
        success: function(model){
            self.render();
            app.navigate('user/' + model.id, false);
            utils.showAlert('Success!', 'User saved successfully', 'alert-success');
        },
        error: function(){
            utils.showAlert('Error', 'An error occurred while trying to save this item', 'alert-error');
        }
    });
}

I have to use 'put' method whit data from any fields except '_id', so it must be smth like:

{"name": "Foo", "email": "[email protected]"}

But every time, doesn't depend on what I do it send

{**"_id": "5083e4a7f4c0c4e270000001"**, "name": "Foo", "email": "[email protected]"}

and this error from server:

MongoError: cannot change _id of a document old:{ _id: ObjectId('5083e4a7f4c0c4e270000001'), name: "Foo" } new:{ _id: "5083e4a7f4c0c4e270000001", name: "Bar", email: "[email protected]" }

Github link: https://github.com/pruntoff/habo

Thanks in advance!

like image 945
Pruntoff Avatar asked Oct 23 '12 13:10

Pruntoff


People also ask

Can _ID be changed in MongoDB?

The _id field is immutable—that is, once a document exists in your MongoDB system, it has, by definition, been assigned an _id, and you cannot change or update its primary key. That said, _id can be overridden when you insert new documents, but by default it will be populated with an ObjectID.

What is $Set in MongoDB?

$set outputs documents that contain all existing fields from the input documents and newly added fields. The $set stage is an alias for $addFields . Both stages are equivalent to a $project stage that explicitly specifies all existing fields in the input documents and adds the new fields.


2 Answers

From looking at your mongo error, the problem is not with mongo, it is just doing what it's supposed to do. It had an object with _id of ObjectId type: ObjectId('xxx') and now you're trying to change that object to have an _id of a String type (_id: "5083e4a7f4c0c4e270000001") and that Mongo apparently does not like.

So, the question is: why did the object have an id of type ObjectId in the first place? How did you set it the first time? If you used some other method to initialize it (I'm guessing server side), you should set the id type to be a String so that it is the same as the one coming from your script library. If you want it to stay an ObjectId, you will need to convert the String coming from your script to an ObjectId before you save it to Mongo.

HTH.

like image 144
TheZuck Avatar answered Sep 27 '22 20:09

TheZuck


MongoDB creates _id as an ObjectID, but doesn't retrieve _id as an ObjectID.

Whether this inconsistency is 'correct behaviour' or not, it is certainly an annoying surprise for most MongoDB users.

You can fix it with:

if ( this._id && ( typeof(this._id) === 'string' ) ) {
  log('Fixing id')
  this._id = mongodb.ObjectID.createFromHexString(this._id)
}

See MongoDB can't update document because _id is string, not ObjectId

like image 45
mikemaccana Avatar answered Sep 27 '22 18:09

mikemaccana