MongoDB 3.4:能否用$reduce实现对象数组转嵌套数组?
Hey everyone, I've already worked out how to convert object arrays into nested arrays using $unwind and $group in MongoDB 3.4, but I'm curious if there's a way to get the same result with $reduce instead. Let me walk you through the details:
Input Data
{ "myArray": [ {"foo":"x", "bar":"y", "important": { "imp_1": "a", "imp_2": "b" } }, {"foo":"x", "bar":"y", "important": { "imp_1": "aa", "imp_3": "bb" } } ] }
Desired Output
{ "myArray": [ {"foo":"x", "bar":"y", "important": [ {"k":"imp_1", "v":"a"}, {"k":"imp_2", "v":"b"} ] }, {"foo":"x", "bar":"y", "important": [ {"k":"imp_1", "v":"aa"}, {"k":"imp_3", "v":"bb"} ] } ] }
Solution with $reduce
Absolutely! You can use $reduce for this task—you'll just need to pair it with $objectToArray (to turn the important object into k-v pairs) and $map to loop through your myArray entries. Here's the working aggregation pipeline:
db.collection.aggregate([ { $project: { myArray: { $map: { input: "$myArray", as: "item", in: { foo: "$$item.foo", bar: "$$item.bar", important: { $reduce: { input: { $objectToArray: "$$item.important" }, initialValue: [], in: { $concatArrays: ["$$value", ["$$this"]] } } } } } } } } ])
If you want a slightly more concise version that still uses $reduce to build the array incrementally, you can swap $concatArrays for $push:
db.collection.aggregate([ { $project: { myArray: { $map: { input: "$myArray", as: "item", in: { foo: "$$item.foo", bar: "$$item.bar", important: { $reduce: { input: { $objectToArray: "$$item.important" }, initialValue: [], in: { $push: ["$$value", "$$this"] } } } } } } } } ])
Quick Breakdown
$maploops through every element inmyArray, letting us transform each item one by one.$objectToArrayconverts theimportantobject into the exactk-varray structure we need for the output.$reducetakes that converted array and builds the finalimportantarray by appending each entry to the initial empty array (either via$concatArraysor$push).
Since both $reduce and $objectToArray were introduced in MongoDB 3.4, this pipeline will work perfectly with your version.
内容的提问来源于stack exchange,提问作者grunci

