Tengo una colección de los siguientes objetos:
{ "_did": "213412323234", "metadata": [ { "id": "Language", "value": "EN" }, { "id": "City", "value": "New York" }, { "id": "Gender", "value": "Male" } ] }Después de usar algunos operadores de canalización (tal vez $proyecto), espero algo como esto:
{ "id": "213412323234", "metadata": { "Language": "EN", "City": "New York", "Gender": "Male" } }Si se conoce la posición de los elementos en el campo de metadata y las claves de los documentos incrustados, puede utilizar la agregación.
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" } } } ])Resultado :
{ "_id" : "213412323234", "metadata" : { "Language" : "EN", "City" : "New York", "Gender" : "Male" } } Si no conoce ninguna de las dos condiciones previas mencionadas anteriormente, puede usar 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"} })Resultado :
> db.foobar.find() { "_id" : "213412323234", "value" : { "Language" : "EN", "City" : "New York", "Gender" : "Male" } } Observe que la clave se ha cambiado a value en lugar de metadatos. Esto se puede arreglar fácilmente usando un $project en aggregation en la colección foobar .
De acuerdo con esta solicitud de función y su solución, se agregará la nueva función para esta funcionalidad: función llamada arrayToObject .
db.foo.aggregate([ {$project: { metadata: { $arrayToObject: { $map: { input: "$metadata", as: "pair", in: ["$$pair.id", "$$pair.value"] } } } }} ])Pero por el momento, no hay solución . Le sugiero que cambie su estructura de datos. Por lo que veo, hay muchas solicitudes de funciones etiquetadas como Principales pero no realizadas durante años.
Pruebe este script de consulta
var results = db.meta.aggregate([{ $project: { id: "$_did", _id: 0, keys: "$metadata.id", values: "$metadata.value" } }]) function object(keys, values) { var obj = {}; for (var index in keys) { obj[keys[index]] = values[index]; } return obj; } results = results.map(function (res) { return { id: res.id, metadata: object(res.keys, res.values) } })