MongoDB 3.6以降では、 $ replaceRoot
$と組み合わせて適用できるパイプラインmergeObjects
newRoot
としての演算子 表現。
この表現
{ "$mergeObjects": ["$subdoc", "$$ROOT"] }
ドキュメントの最上位フィールドをサブドキュメント埋め込みフィールドのフィールドとマージするため、最終的に集約操作は次のようになります。
db.collection.aggregate([
{ "$replaceRoot": {
"newRoot": {
"$mergeObjects": [ "$subdoc", "$$ROOT" ]
}
} },
{ "$project": { "subdoc": 0 } }
])
それ以外の場合は、動的な $ project
をアセンブルするために必要なすべての動的キーを取得するメカニズムが必要になります。 資料。これは、 Map-Reduce
を介して可能です。 。次のmapreduce操作は、 _id
としてすべてのキーを別のコレクションに入力します 値:
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"
})
すべての動的キーのリストを取得するには、結果のコレクションで個別に実行します。
db[mr.result].distinct("_id")
["field2", "field3", ...]
上記のリストがあれば、 $ project
を組み立てることができます ループ内でプロパティが設定されるオブジェクトを作成することにより、パイプラインドキュメントを集約します。通常、 $ project
ドキュメントは次の構造になります:
var project = {
"$project": {
"field1": 1,
"field2": "$subdoc.field2",
"field3": "$subdoc.field3"
}
};
したがって、上記のサブドキュメントキーのリストを使用すると、JavaScriptの reduce()
方法:
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]);