MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Reformater la collection à l'aide du pipeline d'agrégation dans Mongodb

Si la position des éléments dans les metadata le champ et les clés des documents intégrés sont connus et vous pouvez alors utiliser l'agrégation.

db.foo.aggregate([
  {
    $project : {
      data : {
        "Language" : {
          $arrayElemAt : ["$metadata", 0]
        },
        "City" : {
          $arrayElemAt : ["$metadata", 1]
        },
        "Gender" : {
          $arrayElemAt : ["$metadata", 2]
        }
      }
    }
  },
  {
    $project : {
      metadata : {
        Language : "$data.Language.value",
        City : "$data.City.value",
        Gender : "$data.Gender.value"
      }
    }
  }
])

Résultat :

{ "_id" : "213412323234", "metadata" : { "Language" : "EN", "City" : "New York", "Gender" : "Male" } }

Si l'une des deux conditions préalables mentionnées ci-dessus n'est pas connue, vous pouvez utiliser mapReduce .

db.foo.mapReduce(function () {
  var key = this._id;
  var metadata = this.metadata;
  var valueEmit = {};
  for (var i = 0; i < metadata.length; i++) {
    valueEmit[metadata[i].id] = metadata[i].value;
  }
  emit(key, valueEmit)
},
function(key, values) {
  // do nothing as it won't be called 
  // for if value is only one 
  // for a key
},
{
  out : {replace : "foobar"}
})

Résultat :

> db.foobar.find()
{ "_id" : "213412323234", "value" : { "Language" : "EN", "City" : "New York", "Gender" : "Male" } }

Notez que la clé a été remplacée par value à la place des métadonnées. Cela peut être facilement résolu en utilisant un $project en aggregation sur foobar collecte.