¿Cómo actualizar el _id de un Documento MongoDB?

Quiero actualizar un _id MongoDB de un documento. Sé que no es una buena práctica. Pero con alguna razón técnica, necesito actualizarlo. Pero si trato de actualizarlo, tengo:

> db.clients.update({'_id':ObjectId("4cc45467c55f4d2d2a000002")}, {'$set':{'_id':ObjectId("4c8a331bda76c559ef000004")}}); Mod on _id not allowed 

Y la actualización no está hecha. ¿Cómo puedo actualizarlo realmente?

No puedes actualizarlo. Deberá guardar el documento utilizando un nuevo _id y luego eliminar el documento anterior.

 // store the document in a variable doc = db.clients.findOne({_id: ObjectId("4cc45467c55f4d2d2a000002")}) // set a new _id on the document doc._id = ObjectId("4c8a331bda76c559ef000004") // insert the document, using the new _id db.clients.insert(doc) // remove the document with the old _id db.clients.remove({_id: ObjectId("4cc45467c55f4d2d2a000002")}) 

Para hacerlo para toda su colección también puede usar un bucle (basado en el ejemplo de Niels):

 db.status.find().forEach(function(doc){ doc._id=doc.UserId; db.status_new.insert(doc); }); db.status_new.renameCollection("status", true); 

En este caso UserId era la nueva ID que quería usar

En el caso, desea renombrar _id en la misma colección (por ejemplo, si desea anteponer algunos _ids):

 db.someCollection.find().snapshot().forEach(function(doc) { if (doc._id.indexOf("2019:") != 0) { print("Processing: " + doc._id); var oldDocId = doc._id; doc._id = "2019:" + doc._id; db.someCollection.insert(doc); db.someCollection.remove({_id: oldDocId}); } }); 

if (doc._id.indexOf (“2019:”)! = 0) {… necesario para evitar el bucle infinito, ya que forEach elige los documentos insertados, incluso a través del método .snapshot () utilizado.

Aquí tengo una solución que evita múltiples solicitudes, bucles y eliminación de documentos antiguos.

Puede crear fácilmente una nueva idea manualmente usando algo como: _id:ObjectId() Pero sabiendo que Mongo asignará automáticamente un _id si falta, puede usar aggregate para crear un $project contenga todos los campos de su documento, pero omita el campo _id . Luego puede guardarlo con $out

Entonces, si su documento es:

 { "_id":ObjectId("5b5ed345cfbce6787588e480"), "title": "foo", "description": "bar" } 

Entonces tu consulta será:

  db.getCollection('myCollection').aggregate([ {$match: {_id: ObjectId("5b5ed345cfbce6787588e480")} } {$project: { title: '$title', description: '$description' } }, {$out: 'myCollection'} ])