从子文档中减去$ sum

时间:2017-11-08 10:04:53

标签: mongodb mongodb-query aggregation-framework

在我的MongoDB表中给出以下记录:

{
    "_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")
}

我想用特定的tenantId过滤所有记录,然后在子文档中减去我的金额的总和。

我找到了如何汇总子文档:

db.table.aggregate( [
{ $match : { tenantId: "paul" } },
{ $unwind:{ path: "$deposits", preserveNullAndEmptyArrays: true  }},
{ $group: {
    _id: '$_id', 
    deposits: { $sum: '$deposits.amount' },

} } 

]); 但是当我试图从$ price中扣除$ sum时,如

 deposits: { $subtract: [ $price , $sum: '$deposits.amount'  ] },

比我收到错误说

Error: Line 6: Unexpected token :

1 个答案:

答案 0 :(得分:0)

其实你可以这样做:

db.table.aggregate( [
  { "$match" : { "tenantId": "paul" } },
  //{ $unwind:{ path: "$deposits", preserveNullAndEmptyArrays: true  }},
  { "$project":
    "deposits": { "$subtract": ["$price", { "$sum": "$deposits.amount" } ] }
  }}
])

从MongoDB 3.2开始,您实际上可以$project $sum和一组参数(或数组),因此根本不需要$unwind

  

在版本3.2中更改:$ sum在$ group和$ project阶段可用。在早期版本的MongoDB中,$ sum仅在$ group阶段可用。

     

在$ project阶段使用时,$ sum返回每个文档的指定表达式或表达式列表的总和...

" long"方式,这是" old"方法是实际使用$unwind,但您实际上会在$project之后添加$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" ] }
  }}
])

当然,您需要$first累加器才能从$group阶段返回"price"字段,以便在以下阶段使用它。

但是如果你可以preserveNullAndEmptyArrays,那么你实际上拥有MongoDB 3.2,因此最好不要使用语句} $unwind,因为它&#39这样做的速度要快得多。