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.
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);
}
}
);
});
};
Yes, you can. BTW, uniqueness guaranteed by mongodb. Because _id field has a unique index by default.
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.
@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».
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With