56 votes

MongoDB renomme un champ de base de données dans un tableau

Je dois renommer indentifier dans ce :

{ "general" : 
  { "files" : 
    { "file" : 
      [  
        {  "version" : 
          {  "software_program" : "MonkeyPlus",      
             "indentifier" : "6.0.0" 
          } 
        } 
      ] 
    } 
  } 
}

J'ai essayé

db.nrel.component.update(
  {},
  { $rename: {
    "general.files.file.$.version.indentifier" : "general.files.file.$.version.identifier"
  } },
  false, true
)

mais il revient : $rename source may not be dynamic array .

1 votes

$rename ne développe pas les tableaux, doc

0 votes

@Alexander Azarov, des idées pour résoudre ce problème ? J'ai entendu parler de personnes qui copient dans des champs dans lesquels $rename peut aller...

0 votes

Personnellement, j'écris des scripts qui parcourent la collection et font des migrations.

6voto

Cedric Michel Points 84

Je voudrais aussi renommer une propriété dans le tableau : et j'ai utilisé cette méthode.

db.getCollection('YourCollectionName').find({}).snapshot().forEach(function(a){
    a.Array1.forEach(function(b){
        b.Array2.forEach(function(c){
            c.NewPropertyName = c.OldPropertyName;
            delete c["OldPropertyName"];                   
        });
    });
    db.getCollection('YourCollectionName').save(a)  
});

3 votes

snapshot est déprécié à partir de MongoDB 4.0.

0 votes

Vous pourriez également ajouter if(b.hasOwnProperty("xxx")) pour vérifier que la propriété ou le tableau existe.

2voto

loonis Points 424

La solution la plus simple et la plus courte utilise l'agrégat (Mongo 4.0+).

db.myCollection.aggregate([
  {
    $addFields: {
      "myArray.newField": {$arrayElemAt: ["$myArray.oldField", 0] }
    }
  },
  {$project: { "myArray.oldField": false}},
  {$out: {db: "myDb", coll: "myCollection"}}
])

Le problème de l'utilisation de la boucle forEach comme mentionné ci-dessus est la très mauvaise performance lorsque la collection est énorme.

1voto

Wernfried Points 2508

Ma proposition serait la suivante :

db.nrel.component.aggregate([
   { $unwind: "$general.files.file" },
   {
      $set: {
         "general.files.file.version.identifier": {
            $ifNull: ["$general.files.file.version.indentifier", "$general.files.file.version.identifier"]
         }
      }
   },
   { $unset: "general.files.file.version.indentifier" },
   { $set: { "general.files.file": ["$general.files.file"] } },
   { $out: "nrel.component" } // carefully - it replaces entire collection.
])

Cependant, cela ne fonctionne que lorsque le tableau general.files.file n'a qu'un seul document. Il est probable que ce ne sera pas toujours le cas, alors vous pouvez utiliser celui-ci :

db.nrel.componen.aggregate([
   { $unwind: "$general.files.file" },
   {
      $set: {
         "general.files.file.version.identifier": {
            $ifNull: ["$general.files.file.version.indentifier", "$general.files.file.version.identifier"]
         }
      }
   },
   { $unset: "general.files.file.version.indentifier" },
   { $group: { _id: "$_id", general_new: { $addToSet: "$general.files.file" } } },
   { $set: { "general.files.file": "$general_new" } },
   { $unset: "general_new" },
   { $out: "nrel.component" } // carefully - it replaces entire collection.
])

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X