Cómo establecer ids de objetos únicos en documentos incrustados en una colección de MongoDB

El updateMany de MongoDB se puede utilizar para actualizar todos los documentos que coincidan.

Problema

Sin embargo, si quiere establecer nuevos ObjectIDs únicos en su actualización, encontrará que MongoDB establece el mismo ObjectID para cada entrada:

db.getCollection('mypis_collectedpis').updateMany({}, {$set:
     {apps: {
         "com.picockpit/core": {
             meta: {
                 versión: "2.0",
                 nombre: "PiCockpit Core",
                 imagen: "",
                 descripción: "Aplicación principal de PiCockpit.com"
                 }
             },
             id: ObjectId()
         },
      ts: ISODate(“2020-07-23T08:42:41.052Z”)}
    })

imagen

Esto se debe a que el ObjectId se crea una vez y luego se utiliza para cada actualización.

Solución

Es necesario iterar sobre los documentos individuales utilizando un cursor, y establecer los ObjectIDs.

Primer paso

Actualice / establezca los valores que serán los mismos en todos sus documentos.

Sugiero establecer los valores distintos a null al principio en este paso ya:

db.getCollection('mypis_collectedpis').updateMany({}, {$set:
     {apps: {
         "com.picockpit/core": {
             meta: {
                 versión: "2.0",
                 nombre: "PiCockpit Core",
                 imagen: "",
                 descripción: "Aplicación principal de PiCockpit.com"
                 }
             },
             id: null
         },
      ts: ISODate(“2020-07-23T08:42:41.052Z”)}
    })

imagen

NB: Utilizo el Robo 3T para una experiencia más cómoda que el shell de la línea de comandos de MongoDB.

...obtendrás:

imagen

Segundo paso

Iterar a través de los documentos, y actualizar cada uno usando updateOne:

db.getCollection('mypis_collectedpis').find().forEach((pi) => {
     print("Actualizando" + pi.name + " con ObjectId: " + pi._id);
     db.getCollection('mypis_collectedpis').updateOne({_id: pi._id}, {$set: {"apps.id": ObjectId()}});
     })

imagen

tenga en cuenta la notación de puntos para acceder a las entradas de un documento incrustado - ¡para la notación de puntos la clave del elemento debe ir entre comillas!

Por cierto, esta es la salida que genera:

imagen

y este es el resultado, para dos entradas distintas:

imagen

imagen

Los ObjectIDs han sido actualizados con valores distintos.

Nota importante

Tenga en cuenta que en este código no hay bloqueos / no hay transacciones - para que esta solución funcione, tendría que tener acceso exclusivo a la base de datos, o asegurarse de que los datos no se modifican mientras está trabajando en la base de datos.

De lo contrario, habrá que establecer algún tipo de esquema de actualización, un ejercicio que se deja al lector.

Gracias a Maximilian Schwarzmüller por su curso de MongoDB en Udemy y por la excelente documentación en línea de MongoDB.