Itu sangat sulit!
Pertama, solusi sederhana:
db.test.aggregate([
{ "$match": { "user": "Hans" } },
// duplicate each document: one for "age", the other for "childs"
{ $project: { age: "$age", childs: "$childs",
data: {$literal: ["age", "childs"]}}},
{ $unwind: "$data" },
// pivot data to something like { data: "age", value: "40" }
{ $project: { data: "$data",
value: {$cond: [{$eq: ["$data", "age"]},
"$age",
"$childs"]} }},
// Group by data type, and count
{ $group: { _id: {data: "$data", value: "$value" },
count: { $sum: 1 },
value: {$first: "$value"} }},
// aggregate values in an array for each independant (type,value) pair
{ $group: { _id: "$_id.data", values: { $push: { count: "$count", value: "$value" }} }} ,
// project value to the correctly name field
{ $project: { result: {$cond: [{$eq: ["$_id", "age"]},
{age: "$values" },
{childs: "$values"}]} }},
// group all data in the result array, and remove unneeded `_id` field
{ $group: { _id: null, result: { $push: "$result" }}},
{ $project: { _id: 0, result: 1}}
])
Memproduksi:
{
"result" : [
{
"age" : [
{
"count" : 3,
"value" : "40"
},
{
"count" : 1,
"value" : "50"
}
]
},
{
"childs" : [
{
"count" : 1,
"value" : "1"
},
{
"count" : 3,
"value" : "2"
}
]
}
]
}
Dan sekarang, untuk beberapa penjelasan:
Salah satu masalah utama di sini adalah bahwa setiap dokumen yang masuk harus menjadi bagian dari dua jumlah yang berbeda. Saya memecahkannya dengan menambahkan array literal ["age", "childs"]
ke dokumen Anda, dan kemudian membukanya dengan larik itu. Dengan begitu, setiap dokumen akan ditampilkan dua kali pada tahap selanjutnya.
Setelah selesai, untuk memudahkan pemrosesan, saya mengubah representasi data menjadi sesuatu yang jauh lebih mudah dikelola seperti { data: "age", value: "40" }
Langkah-langkah berikut akan melakukan agregasi data per-se. Hingga $project
ketiga langkah yang akan memetakan bidang nilai ke age
yang sesuai atau childs
lapangan.
Dua langkah terakhir hanya akan membungkus dua dokumen menjadi satu, menghapus _id
. yang tidak diperlukan lapangan.
Pffff!