Verwenden Sie für MongoDB 3.6 und höher das Aggregationsframework mit einem $replaceRoot
Pipeline, die in Verbindung mit $mergeObjects
Operator als newRoot
Ausdruck.
Dieser Ausdruck
{ "$mergeObjects": ["$subdoc", "$$ROOT"] }
wird die Felder der obersten Ebene im Dokument mit denen in den eingebetteten Feldern des Unterdokuments zusammenführen, sodass Ihre aggregierte Operation am Ende wie folgt aussieht:
db.collection.aggregate([
{ "$replaceRoot": {
"newRoot": {
"$mergeObjects": [ "$subdoc", "$$ROOT" ]
}
} },
{ "$project": { "subdoc": 0 } }
])
Andernfalls benötigen Sie einen Mechanismus, um alle dynamischen Schlüssel zu erhalten, die Sie zum Zusammenstellen des dynamischen $project
benötigen dokumentieren. Dies ist möglich durch Map-Reduce
. Die folgende mapreduce-Operation füllt eine separate Sammlung mit allen Schlüsseln als _id
Werte:
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"
})
Um eine Liste aller dynamischen Schlüssel zu erhalten, führen Sie den Befehl „distinct“ für die resultierende Sammlung aus:
db[mr.result].distinct("_id")
["field2", "field3", ...]
Anhand der obigen Liste können Sie nun Ihr $project
zusammenstellen Aggregations-Pipeline-Dokument, indem Sie ein Objekt erstellen, dessen Eigenschaften in einer Schleife festgelegt werden. Normalerweise Ihr $project
Dokument wird diese Struktur haben:
var project = {
"$project": {
"field1": 1,
"field2": "$subdoc.field2",
"field3": "$subdoc.field3"
}
};
Wenn Sie also die obige Liste von Unterdokumentschlüsseln verwenden, können Sie das obige mithilfe von JavaScripts reduce()
Methode:
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]);