MongoDB按字段分组并将子文档合并至父文档的实现方法
Got it, let's walk through how to solve this aggregation task in MongoDB. You want to group your documents by the a field, then merge each group's documents into a parent structure using one of the child document's fields as a key. Let's start with clarifying the input and possible desired outputs, then jump into the aggregation pipeline.
原始输入文档
First, here's your raw data formatted properly:
[ { "_id" : "1", "a" : "11", "b" : "o11", "c" : "s11" }, { "_id" : "2", "a" : "22", "b" : "o22", "c" : "s22" }, { "_id" : "3", "a" : "11", "b" : "o12", "c" : "s12" }, { "_id" : "4", "a" : "11", "b" : "o13", "c" : "s13" }, { "_id" : "5", "a" : "22", "b" : "o23", "c" : "s23" } ]
常见的期望输出结构
I'll cover two common scenarios based on what you might mean by "merge subdocuments using a field as the key":
场景1:以b为键,c为对应值
If you want to map each b value directly to its c value under the grouped a field, the result would look like this:
[ { "a": "11", "items": { "o11": "s11", "o12": "s12", "o13": "s13" } }, { "a": "22", "items": { "o22": "s22", "o23": "s23" } } ]
场景2:以b为键,对应整个子文档
If you want to preserve the full subdocument under each b key, the result would be:
[ { "a": "11", "items": { "o11": { "_id": "1", "b": "o11", "c": "s11" }, "o12": { "_id": "3", "b": "o12", "c": "s12" }, "o13": { "_id": "4", "b": "o13", "c": "s13" } } }, { "a": "22", "items": { "o22": { "_id": "2", "b": "o22", "c": "s22" }, "o23": { "_id": "5", "b": "o23", "c": "s23" } } } ]
对应的聚合管道
Let's build the pipeline for each scenario.
场景1的聚合代码
db.yourCollectionName.aggregate([ // Step 1: Group by 'a' and collect { key: b, value: c } pairs { $group: { _id: "$a", keyValuePairs: { $push: { k: "$b", // Use 'b' as the key v: "$c" // Use 'c' as the corresponding value } } } }, // Step 2: Convert the array of key-value pairs into an object { $project: { _id: 0, // Hide the default _id from grouping a: "$_id", // Rename the grouped _id back to 'a' items: { $arrayToObject: "$keyValuePairs" } // Turn the array into a nested object } } ])
场景2的聚合代码
db.yourCollectionName.aggregate([ // Step 1: Group by 'a' and collect { key: b, value: full document } pairs { $group: { _id: "$a", keyDocPairs: { $push: { k: "$b", // Use 'b' as the key v: { // Include all fields from the original document except 'a' (or include it if needed) _id: "$_id", b: "$b", c: "$c" } } } } }, // Step 2: Convert the array of key-document pairs into an object { $project: { _id: 0, a: "$_id", items: { $arrayToObject: "$keyDocPairs" } } } ])
关键知识点解释
$group: This stage groups documents by theafield, and uses$pushto collect the key-value (or key-document) pairs into an array for each group.$arrayToObject: This MongoDB operator takes an array of{k: "...", v: "..."}objects and converts it into a single object where eachkbecomes a key, mapped to its correspondingv.
Just replace yourCollectionName with the actual name of your collection, and adjust the k and v fields in the $push stage if you want to use a different field as the key (e.g., use c as the key instead of b).
内容的提问来源于stack exchange,提问作者vanba06

