Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I'm doing a rest api to exchange data between a mongo database and a web app. These data are json formatted.

I have a trouble when it comes to update a document:

cannot change _id of a document.

As a matter of fact, in my JSON the _id of the doc is stored as a string and deserialized as a string. Whereas it is stored as an ObjectID in mongo. This explains why mongo raises an error.

  • In mongo: _id: ObjectId('51051fd25b442a5849000001')
  • In JSON: _id:"51051fd25b442a5849000001"

To avoid this I manually convert the _id property from a string to an ObjectID. But It seems ugly and will fail with other BSON types.

Q: Is there a clean way to avoid that or to do a nice JSON/BSON conversion?

Below is the code I use to update a document. I'm using nodejs with express and mongodb with the native driver.

exports.updateById = function(req, res) {
var id = req.params.id;
var map = req.body;

map._id = new ObjectID.createFromHexString( map._id); // Manual conversion. How to avoid this???

console.log( 'Updating map: ' + id);
console.log( 'Map: ' + JSON.stringify( map));

db.collection('maps', function(err, collection) {
    if(err) throw err;
    collection.update(
        {'_id': new BSON.ObjectID(id)}, map, {safe:true}, 
        function(err, result) {
            if (err) {
                console.log('Updating map err: ' + JSON.stringify( err));
                res.json( 500, {'message':'An error has occurred while updating the map', 'error': err});
            } else {
                console.log('Updating succeed');
                res.send(map);
            }
        }
    );
});

};

like image 991
t4ncr3d3 Avatar asked Jan 29 '13 14:01

t4ncr3d3


People also ask

Can MongoDB _id be string?

Yes, you can. BTW, uniqueness guaranteed by mongodb. Because _id field has a unique index by default.

Can we update _id field 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.

Is _id mandatory in MongoDB?

@KevinMeredith As specified here, yes, an _id field is mandatory. «In MongoDB, each document stored in a collection requires a unique _id field that acts as a primary key. If an inserted document omits the _id field, the MongoDB driver automatically generates an ObjectId for the _id field».

Is Mongoose ObjectId a string?

Mongoose casts 24 char strings to ObjectIds for you based on your schema paths. There are several other values that Mongoose can cast to ObjectIds. The key lesson is that an ObjectId is 12 arbitrary bytes. Any 12 byte buffer or 12 character string is a valid ObjectId.


1 Answers

Because you can't modify the _id field, a better approach is to simply remove the that field from your map object instead of converting it to an ObjectId.

So this:

delete map._id;

instead of this:

map._id = new ObjectID.createFromHexString( map._id);

If you want to return the updated object like you're attempting with res.send(map);, you should be using findAndModify instead of update so you have access to the resulting doc and not just what was posted.

like image 161
JohnnyHK Avatar answered Nov 15 '22 15:11

JohnnyHK