Per MongoDB 3.6 e versioni successive, utilizzare il framework di aggregazione con un $replaceRoot
pipeline che può essere applicata insieme a $mergeObjects
operatore come newRoot
espressione.
Questa espressione
{ "$mergeObjects": ["$subdoc", "$$ROOT"] }
unirà i campi di livello superiore nel documento con quelli nei campi incorporati del sottodoc, quindi alla fine l'operazione di aggregazione sarà la seguente:
db.collection.aggregate([
{ "$replaceRoot": {
"newRoot": {
"$mergeObjects": [ "$subdoc", "$$ROOT" ]
}
} },
{ "$project": { "subdoc": 0 } }
])
Altrimenti avresti bisogno di un meccanismo per ottenere tutte le chiavi dinamiche di cui hai bisogno per assemblare il $project
dinamico documento. Ciò è possibile tramite Map-Reduce
. La seguente operazione mapreduce popolerà una raccolta separata con tutte le chiavi come _id
valori:
mr = db.runCommand({
"mapreduce": "my_collection",
"map" : function() {
for (var key in this.subdoc) { emit(key, null); }
},
"reduce" : function(key, stuff) { return null; },
"out": "my_collection" + "_keys"
})
Per ottenere un elenco di tutte le chiavi dinamiche, esegui distinto sulla raccolta risultante:
db[mr.result].distinct("_id")
["field2", "field3", ...]
Ora, dato l'elenco sopra, puoi assemblare il tuo $project
documento della pipeline di aggregazione creando un oggetto con le sue proprietà impostate all'interno di un ciclo. Normalmente il tuo $project
il documento avrà questa struttura:
var project = {
"$project": {
"field1": 1,
"field2": "$subdoc.field2",
"field3": "$subdoc.field3"
}
};
Quindi, usando l'elenco sopra di chiavi di documenti secondari, puoi costruire dinamicamente quanto sopra usando reduce()
metodo:
var subdocKeys = db[mr.result].distinct("_id"),
obj = subdocKeys.reduce(function (o, v){
o[v] = "$subdoc." + v;
return o;
}, { "field1": 1 }),
project = { "$project": obj };
db.collection.aggregate([project]);