Subtract $sum from Sub-document

别说谁变了你拦得住时间么 提交于 2019-12-20 06:27:26

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!