Comment définir des identifiants d'objet uniques dans les documents intégrés à une collection MongoDB ?

La fonction updateMany de MongoDB peut être utilisée pour mettre à jour tous les documents qui correspondent.

Problème

Toutefois, si vous souhaitez définir de nouveaux ObjectID uniques dans votre mise à jour, vous constaterez que MongoDB définit le même ObjectID pour chaque entrée :

db.getCollection('mypis_collectedpis').updateMany({}, {$set :
     {apps : {
         "com.picockpit/core" : {
             meta : {
                 version : "2.0",
                 nom : "PiCockpit Core",
                 l'image : "",
                 description : "Application centrale de PiCockpit.com"
                 }
             },
             id : ObjectId()
         },
      ts : ISODate(“2020-07-23T08:42:41.052Z”)}
    })

image

En effet, l'ObjectId est créé une fois et est ensuite utilisé pour chaque mise à jour.

Solution

Vous devez itérer sur les documents individuels à l'aide d'un curseur et définir les ObjectID.

Première étape

Mettez à jour / définissez les valeurs qui seront les mêmes dans tous vos documents.

Je suggère de mettre les valeurs distinctes à null dans un premier temps dans cette étape déjà :

db.getCollection('mypis_collectedpis').updateMany({}, {$set :
     {apps : {
         "com.picockpit/core" : {
             meta : {
                 version : "2.0",
                 nom : "PiCockpit Core",
                 l'image : "",
                 description : "Application centrale de PiCockpit.com"
                 }
             },
             id : null
         },
      ts : ISODate(“2020-07-23T08:42:41.052Z”)}
    })

image

NB : J'utilise Robo 3T pour une expérience plus confortable que le shell de la ligne de commande MongoDB.

vous obtiendrez :

image

Deuxième étape

Interroger les documents, et mettre à jour chacun d'entre eux en utilisant updateOne :

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

image

notez la notation par points pour accéder aux entrées dans un document incorporé - pour la notation par points, la clé de l'élément doit être placée entre guillemets !

Voici d'ailleurs le résultat que cela génère :

image

et voici le résultat, pour deux entrées distinctes :

image

image

Les ObjectIDs ont été mis à jour avec des valeurs distinctes.

Remarque importante

Notez que dans ce code, il n'y a pas de verrous / pas de transactions - pour que cette solution fonctionne, vous devriez avoir un accès exclusif à la base de données, ou vous assurer que les données ne sont pas modifiées pendant que vous travaillez sur la base de données.

Sinon, il faut mettre en place un système de mise à jour - un exercice laissé au soin du lecteur.

Merci à Maximilian Schwarzmüller pour son cours Udemy MongoDB, et l'excellente documentation en ligne de MongoDB !