问题
Given the following record in my MongoDB table:
{
"_id" : ObjectId("5a00c1c71680084c55811ae2"),
"name" : "test",
"tenantId" : "paul",
"price" : 300,
"deposits" : [
{
"amount" : 100,
"date" : ISODate("2017-11-07T14:08:19.324Z"),
"_id" : ObjectId("5a01be55424b0f8922a5b472")
},
{
"amount" : 50,
"date" : ISODate("2017-11-87T14:08:19.324Z"),
"_id" : ObjectId("5a01be55424b0f8922a5b473")
}
],
"attention" : "",
"due" : ISODate("2017-10-26T22:00:00.000Z")
}
I would like to filter all the records with a specific tenantId, and then subtract the SUM of my amounts in the subdocument.
I found out how to Sum the Subdocument:
db.table.aggregate( [
{ $match : { tenantId: "paul" } },
{ $unwind:{ path: "$deposits", preserveNullAndEmptyArrays: true }},
{ $group: {
_id: '$_id',
deposits: { $sum: '$deposits.amount' },
} }
] ); but when i try to subtract the $sum from $price like
deposits: { $subtract: [ $price , $sum: '$deposits.amount' ] },
than i get an error saying
Error: Line 6: Unexpected token :
回答1:
Actually you can simply do:
db.table.aggregate( [
{ "$match" : { "tenantId": "paul" } },
//{ $unwind:{ path: "$deposits", preserveNullAndEmptyArrays: true }},
{ "$project":
"deposits": { "$subtract": ["$price", { "$sum": "$deposits.amount" } ] }
}}
])
Since MongoDB 3.2 you can actually $project with $sum and an array of arguments ( or an array ) and therefore do not need to $unwind
at all.
Changed in version 3.2: $sum is available in the $group and $project stages. In previous versions of MongoDB, $sum is available in the $group stage only.
When used in the $project stage, $sum returns the sum of the specified expression or list of expressions for each document ...
The "long" way, which is the "old" way is to actually use $unwind, but you would then actually add a $project following the $group:
db.table.aggregate( [
{ "$match" : { "tenantId": "paul" } },
{ $unwind:{ path: "$deposits", preserveNullAndEmptyArrays: true }},
{ "$group":
"_id": "$_id",
"price": { "$first": "$price" },
"deposits": { "$sum": "$deposits.amount" }
}},
{ "$project": {
"deposits": { "$subtract": [ "$price", "$deposits" ] }
}}
])
And of course you then need the $first accumulator in order to return the "price"
field from the $group stage so it can be used in the following stage.
But if you can do preserveNullAndEmptyArrays
, then you actually have MongoDB 3.2, and therefore are better off using the statement without the $unwind at all, since it's much faster to do it that way.
来源:https://stackoverflow.com/questions/47176715/subtract-sum-from-sub-document