Bentuk paling sederhana dari ini adalah untuk menjaga hal-hal dikunci dengan "parameter" "nama":
db.collection.aggregate(
// Unwind the array
{ "$unwind": "$parameter"},
// Group on the "_id" and "name" and $sum "value"
{ "$group": {
"_id": {
"userId": "$userId",
"name": "$parameter.name"
},
"value": { "$sum": "$parameter.value" }
}},
// Put things into an array for "nice" processing
{ "$group": {
"_id": "$_id.userId",
"values": { "$push": {
"name": "$_id.name",
"value": "$value"
}}
}}
)
Jika Anda benar-benar perlu memiliki "nilai" nama sebagai nilai bidang, Anda bisa lakukan hal berikut. Tetapi karena Anda "memproyeksikan" bidang/properti maka Anda harus menentukan semuanya dalam kode Anda . Anda tidak dapat menjadi "dinamis" lagi dan Anda mengkode/menghasilkan masing-masing:
db.collection.aggregate([
// Unwind the array
{ "$unwind": "$parameter"},
// Group on the "_id" and "name" and $sum "value"
{ "$group": {
"_id": {
"userId": "$userId",
"name": "$parameter.name"
},
"value": { "$sum": "$parameter.value"}
}},
// Project out discrete "field" names with $cond
{ "$project": {
"name1": { "$cond": [
{ "$eq": [ "$_id.name", "name1" ] },
"$value",
0
]},
"name2": { "$cond": [
{ "$eq": [ "$_id.name", "name2" ] },
"$value",
0
]},
"name3": { "$cond": [
{ "$eq": [ "$_id.name", "name3" ] },
"$value",
0
]},
}},
// The $cond put "0" values in there. So clean up with $group and $sum
{ "$group": {
_id: "$_id.userId",
"name1": { "$sum": "$name1" },
"name2": { "$sum": "$name2" },
"name3": { "$sum": "$name3" }
}}
])
Jadi sementara langkah ekstra memberi Anda hasil yang Anda inginkan (baik dengan tugas akhir untuk mengubah _id
ke userId
), menurut saya versi singkatnya cukup bisa diterapkan, kecuali jika Anda benar-benar membutuhkannya. Pertimbangkan juga output dari sana:
{
"_id" : ObjectId("53245016ea402b31d77b0372"),
"values" : [
{
"name" : "name3",
"value" : 2
},
{
"name" : "name2",
"value" : 0
},
{
"name" : "name1",
"value" : 150
}
]
}
Jadi itulah yang akan saya gunakan, secara pribadi. Tapi pilihanmu.