根据您的可用版本和实用性,您可能只需应用 $reduce 和 $concatArrays 以便在分组文档中“加入”生成的“数组数组”:
db.getCollection('stuff').aggregate([
{ "$group": {
"_id": {
"product": "$product", "state": "$state"
},
"nondnd": { "$push": "$nondnd" },
"dnd": { "$push": "$dnd" },
"land": { "$push": "$land" },
"emails": { "$push": "$emails" }
}},
{ "$addFields": {
"nondnd": {
"$reduce": {
"input": "$nondnd",
"initialValue": [],
"in": { "$concatArrays": [ "$$value", "$$this" ] }
}
},
"dnd": {
"$reduce": {
"input": "$dnd",
"initialValue": [],
"in": { "$concatArrays": [ "$$value", "$$this" ] }
}
},
"land": {
"$reduce": {
"input": "$land",
"initialValue": [],
"in": { "$concatArrays": [ "$$value", "$$this" ] }
}
},
"emails": {
"$reduce": {
"input": "$emails",
"initialValue": [],
"in": { "$concatArrays": [ "$$value", "$$this" ] }
}
}
}}
])
或者甚至是你真的不喜欢重复自己的“超现代”(但你可能无论如何都应该生成管道阶段):
db.getCollection('stuff').aggregate([
{ "$project": {
"product": 1,
"state": 1,
"data": {
"$filter": {
"input": { "$objectToArray": "$$ROOT" },
"cond": { "$in": [ "$$this.k", ["nondnd","dnd","land","emails"] ] }
}
}
}},
{ "$unwind": "$data" },
{ "$unwind": "$data.v" },
{ "$group": {
"_id": {
"product": "$product",
"state": "$state",
"k": "$data.k"
},
"v": { "$push": "$data.v" }
}},
{ "$group": {
"_id": {
"product": "$_id.product",
"state": "$_id.state"
},
"data": { "$push": { "k": "$_id.k", "v": "$v" } }
}},
{ "$replaceRoot": {
"newRoot": {
"$arrayToObject": {
"$concatArrays": [
[{ "k": "_id", "v": "$_id" }],
{ "$map": {
"input": ["nondnd","dnd","land","emails"],
"in": {
"$cond": {
"if": { "$ne": [{ "$indexOfArray": [ "$data.k", "$$this" ] },-1] },
"then": {
"$arrayElemAt": [
"$data",
{ "$indexOfArray": [ "$data.k", "$$this" ] }
]
},
"else": { "k": "$$this", "v": [] }
}
}
}}
]
}
}
}}
])
或者您可以交替地在源连接数组并将它们映射到一个类型。然后分组后重构:
db.getCollection('stuff').aggregate([
{ "$project": {
"product": 1,
"state": 1,
"combined": {
"$concatArrays": [
{ "$map": {
"input": "$nondnd",
"in": { "t": "nondnd", "v": "$$this" }
}},
{ "$map": {
"input": "$dnd",
"in": { "t": "dnd", "v": "$$this" }
}},
{ "$map": {
"input": "$land",
"in": { "t": "land", "v": "$$this" }
}},
{ "$map": {
"input": "$emails",
"in": { "t": "emails", "v": "$$this" }
}}
]
}
}},
{ "$unwind": "$combined" },
{ "$group": {
"_id": {
"product": "$product", "state": "$state"
},
"combined": { "$push": "$combined" }
}},
{ "$project": {
"nondnd": {
"$map": {
"input": {
"$filter": {
"input": "$combined",
"cond": { "$eq": [ "$$this.t", "nondnd" ] }
}
},
"in": "$$this.v"
}
},
"dnd": {
"$map": {
"input": {
"$filter": {
"input": "$combined",
"cond": { "$eq": [ "$$this.t", "dnd" ] }
}
},
"in": "$$this.v"
}
},
"land": {
"$map": {
"input": {
"$filter": {
"input": "$combined",
"cond": { "$eq": [ "$$this.t", "land" ] }
}
},
"in": "$$this.v"
}
},
"emails": {
"$map": {
"input": {
"$filter": {
"input": "$combined",
"cond": { "$eq": [ "$$this.t", "emails" ] }
}
},
"in": "$$this.v"
}
}
}}
])
所以很大程度上取决于$map 和$filter 来构造和解构单个连接数组的内容,这对$unwind 来说当然是完美的。
每个案例的结果都是一样的:
/* 1 */
{
"_id" : {
"product" : "product1",
"state" : "state2"
},
"nondnd" : [
9.0,
8.0,
2.0
],
"dnd" : [
10.0,
7.0,
11.0
],
"land" : [
1.0,
3.0
],
"emails" : [
"e",
"g"
]
}
/* 2 */
{
"_id" : {
"product" : "product1",
"state" : "state1"
},
"nondnd" : [
1.0,
2.0,
3.0,
9.0,
8.0,
2.0
],
"dnd" : [
4.0,
5.0,
10.0,
7.0,
11.0
],
"land" : [
2.0,
4.0,
6.0,
8.0
],
"emails" : [
"a",
"b",
"c",
"d"
]
}