Вы были не далеко, операция, которую вы действительно хотите, это $arrayElemAt
вместо
db.getCollection('AccountInfo').aggregate([
{ "$match": { "_id.@objectName" : "AccountBalance" }},
{ "$group": {
"_id": "$_id.branchId",
"total": {
"$sum": {
"$arrayElemAt": [ "$Versions.value", -1 ]
}
}
}},
{ "$sort": { "total": -1 } }
])
$slice
возвращает "массив", поэтому вам все еще нужно $sum
элементов:
db.getCollection('AccountInfo').aggregate([
{ "$match": { "_id.@objectName" : "AccountBalance" }},
{ "$group": {
"_id": "$_id.branchId",
"total": {
"$sum": {
"$sum": { "$slice": [ "$Versions.value", -1 ] }
}
}
}},
{ "$sort": { "total": -1 } }
])
Но обычно лучше получить единственный элемент, когда вы действительно это имеете в виду. Используйте $slice
только там, где вы на самом деле имеете в виду «несколько» элементов массива.
Если вы точно не знали, что "version"
был «последним» элементом массива, вы можете сопоставить его с $indexOfArray
и $max
:
db.getCollection('AccountInfo').aggregate([
{ "$match": { "_id.@objectName" : "AccountBalance" }},
{ "$group": {
"_id": "$_id.branchId",
"total": {
"$sum": {
"$arrayElemAt": [
"$Versions.value",
{ "$indexOfArray": [
"$Versions.version",
{ "$max": "$Versions.version" }
]}
]
}
}
}},
{ "$sort": { "total": -1 } }
])
Также научитесь «всегда» $match
первым и не $project
элементам, которые вы можете сделать то же самое «inline» в пределах $group
. Это делает ваш запрос намного более эффективным.
Все возвращают один и тот же результат:
{ "_id" : "AXC", "total" : NumberDecimal("9612.88") }