如何从猫鼬中独立的两个子文档数组中获取总和

时间:2019-10-31 11:56:49

标签: node.js express mongoose aggregation-framework

我有这个模式

    var salesExpenseSchema = new Schema({

        date : {
            month: Number
        },  

        sales: [{amount : Schema.Types.Decimal128}],

        expenses: [{amount : Schema.Types.Decimal128}]

});

数据库记录示例如下

{
    _id:'5dbac5dfa1488240cbc4f838',
    date:{month:11},
    sales:[{amount:3000},{amount:5000}],
    expenses: [{amount:5000},{amount:500}]
},
{
    _id:'5dbac5dfa1488240cbc4f838',
    date:{month:10},
    sales:[{amount:2000},{amount:5000}],
    expenses: [{amount:500},{amount:800}]
},
{
    _id:'5dbac5dfa1488240cbc4f838',
    date:{month:09},
    sales:[{amount:2000},{amount:4000}],
    expenses: [{amount:200},{amount:300}]
}

现在我想获得销售和费用总和。

我已将$ unwind的Aggregate用于销售和支出,如下所示:

SalesExpense.aggregate([
              {$unwind: "$sales"},
              {$unwind: "$expenses"},
              {$group:{
                    _id:'$_id',
                    sales:{$sum: "$sales.sellPrices"},
                    expenses:{$sum: "$expenses.amount"},
                  }
              },

但是问题是... 如果一个数组文档中有数据,而另一个数组中没有数据,则它给出0,即无法获得真实的总和。也就是说,如果有销售但没有费用,则它们的总和变为0,反之亦然。

我想获取销售和费用的总和,而不管其中之一没有数据。我该如何实现?

编辑:

我已经编辑了问题,并在架构和数据库记录中添加了date对象:我想基于每个月(即...每个月都有自己的销售和费用)进行汇总。 ..一个时间表,每个月都有自己的销售和费用。

我尝试在$ project之前使用$ group

{$group:{
_id:'$date.month'}}

但是似乎没有给出预期的结果。

我想要这样的输出:

[
        {
            "month": "11",
            "sales": {
                "$numberDecimal": "8000"
            },
            "expenses": {
                "$numberDecimal": "5500"
            }
        },

        {
            "month": "10",
            "sales": {
                "$numberDecimal": "7000"
            },
            "expenses": {
                "$numberDecimal": "1100"
            }
        },
        {
            "month": "09",
            "sales": {
                "$numberDecimal": "6000"
            },
            "expenses": {
                "$numberDecimal": "500"
            }
        },
    ]

我该如何实现?

1 个答案:

答案 0 :(得分:0)

您可以按月分组并获得总计:

db.collection.aggregate([
  {
    $group: {
      _id: "$date.month",
      "sales": {
        "$sum": {
          "$sum": "$sales.amount"
        }
      },
      "expenses": {
        "$sum": {
          "$sum": "$expenses.amount"
        }
      }
    }
  }
])

样本数据:

[
  {
    _id: "5dbac5dfa1488240cbc4f838",
    date: {
      month: 11
    },
    sales: [
      {
        amount: 1
      },
      {
        amount: 2
      }
    ],
    expenses: []
  },
  {
    _id: "5dbac5dfa1488240cbc4f839",
    date: {
      month: 11
    },
    sales: [
      {
        amount: 5
      },
      {
        amount: 6
      }
    ],
    expenses: [
      {
        amount: 7
      },
      {
        amount: 8
      }
    ]
  },
  {
    _id: "5dbac5dfa1488240cbc4f840",
    date: {
      month: 12
    },
    sales: [],
    expenses: [
      {
        amount: 7
      },
      {
        amount: 8
      }
    ]
  }
]

结果:

[
  {
    "_id": 12,
    "expenses": 15,
    "sales": 0
  },
  {
    "_id": 11,
    "expenses": 15,
    "sales": 14
  }
]

游乐场:

https://mongoplayground.net/p/K9ofoZx5ORI