【问题标题】:MongoDB: get sum by year/month with nested valuesMongoDB:使用嵌套值按年/月获取总和
【发布时间】:2021-02-22 21:59:53
【问题描述】:

我正在尝试对具有嵌套金额的集合求和(按月/年支出) - 没有运气。

这是集合(摘录):

[
{
    "_id" : ObjectId("5faaf88d0657287993e541a5"),
    "segment" : {
        "l1" : "Segment A",
        "l2" : "001"
    },
    "invoiceNo" : "2020.10283940",
    "invoicePos" : 3,
    "date" : ISODate("2019-09-06T00:00:00.000Z"),
    "amount" : {
        "document" : {
            "amount" : NumberDecimal("125.000000000000"),
            "currCode" : "USD"
        },
        "local" : {
            "amount" : NumberDecimal("123.800000000000"),
            "currCode" : "CHF"
        },
        "global" : {
            "amount" : NumberDecimal("123.800000000000"),
            "currCode" : "CHF"
        }
    }
},
...
]

我想以“全球”货币总结每月的总发票量。

我在 MongoDB 上试过这个查询:

db.invoices.aggregate( 
       {$project : { 
              month : {$month : "$date"}, 
              year : {$year :  "$date"},
              amount : 1
          }},
        {$unwind: '$amount'}, 
        {$group : { 
                _id : {month : "$month" ,year : "$year" },  
              total : {$sum : "$amount.global.amount"} 
        }})

我得到的结果是:

/* 1 */
{
    "_id" : ObjectId("5faaf88d0657287993e541a5"),
    "amount" : {
        "document" : {
            "amount" : NumberDecimal("125.000000000000"),
            "currCode" : "USD"
        },
        "local" : {
            "amount" : NumberDecimal("123.800000000000"),
            "currCode" : "CHF"
        },
        "global" : {
            "amount" : NumberDecimal("123.800000000000"),
            "currCode" : "CHF"
        }
    },
    "month" : 9,
    "year" : 2019
}

/* 2 */
{
    "_id" : ObjectId("5faaf88d0657287993e541ac"),
    "amount" : {
        "document" : {
            "amount" : NumberDecimal("105.560000000000"),
            "currCode" : "CHF"
        },
        "local" : {
            "amount" : NumberDecimal("105.560000000000"),
            "currCode" : "CHF"
        },
        "global" : {
            "amount" : NumberDecimal("105.560000000000"),
            "currCode" : "CHF"
        }
    },
    "month" : 11,
    "year" : 2020
}

然而,这并没有汇总每个月的所有发票,而是看起来像单个发票行 - 没有汇总。

我想得到这样的结果:

[
  {
    "month": 11,
    "year": 2020,
    "amount" : NumberDecimal("99999.99") 
  },
  {
    "month": 10,
    "year": 2020,
    "amount" : NumberDecimal("99999.99") 
  },
  {
    "month": 9,
    "year": 2020,
    "amount" : NumberDecimal("99999.99") 
  }
]

我的查询有什么问题?

【问题讨论】:

    标签: mongodb sum aggregate nested-object


    【解决方案1】:

    这会有帮助吗?

    db.invoices.aggregate([
      {
        $group: {
          _id: {
            month: {
              $month: "$date"
            },
            year: {
              $year: "$date"
            }
          },
          total: {
            $sum: "$amount.global.amount"
          }
        }
      },
      {$sort:{"_id.year":-1, "_id.month":-1}}
    ])
    

    Playground

    如果您需要任何额外的解释,请告诉我,但代码非常简短且不言自明。

    【讨论】:

    • 很好,很有效!但是,对于 500k+ 条记录,此方法无法在 30 秒内完成任务。是否有其他方式来执行查询?
    • 您可以尝试将 {$limit:} 作为 $sort 之后的一个阶段,然后在它找到最佳文档后,它会停止寻找更多 @Herdy
    【解决方案2】:

    原则上你的聚合管道是好的,有一些错误:

    • 聚合管道需要一个数组
    • $unwind 没用,因为 $amount 不是数组。一个元素输入 -> 一个文档输出
    • 可以直接使用日期函数

    所以,简短而简单:

    db.invoices.aggregate([
      {
        $group: {
          _id: { month: { $month: "$date" }, year: { $year: "$date" } },
          total: { $sum: "$amount.global.amount" }
        }
      }
    ])
    

    【讨论】:

      猜你喜欢
      • 2018-07-27
      • 2021-05-17
      • 2021-02-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多