簡體   English   中英

如何根據MongoDB中的條件投影子文檔中字段的總和?

[英]How to project a sum of a field in a sub-document based on a condition in MongoDB?

我有一個包含以下文檔的客戶集合:

{
  "_id": 1,
  firstname: "John",
  lastname: "Doe",
  credits: [
    {
      cDate: "2020-01-16",
      cAmount: 350
    },
    {
      cDate: "2021-02-07",
      cAmount: 180
    },
    {
      cDate: "2021-06-25",
      cAmount: 650
    },
  ]
}
{
  "_id": 2,
  firstname: "Bob",
  lastname: "Smith",
  credits: [
    {
      cDate: "2020-03-19",
      cAmount: 200
    },
    {
      cDate: "2020-08-20",
      cAmount: 90
    },
    {
      cDate: "2021-11-11",
      cAmount: 300
    },
  ]
}

現在我想返回特定年份(即 2021 年)的總支出。
數據應如下所示:

{"firstname": "John", "lastname": "Doe", "total": 830},
{"firstname": "Bob", "lastname": "Smith", "total": 300}

首先,我嘗試在預期年份(2021 年)內匹配包含cDates的記錄以減少記錄數(實際數據集有數百個客戶),然后投影需要的字段:

Customer.aggregate([
  {
    $match: {
      credits: {
        $elemMatch: {
          cDate: {
            $gte: ISODate("2021-01-01"),
            $lte: ISODate("2021-12-31"),
          },
        },
      },
    },
  },
  {
    $project: {      
      _id: 0,
      firstname: 1,
      lastname: 1,
      total: {
        $sum: "$credits.cAmount",
      },
    },
  }
])

結果是:

{"firstname": "John", "lastname": "Doe", "total": 1180},
{"firstname": "Bob", "lastname": "Smith", "total": 590}

差不多了,現在我想跳過不包含預期年份 (2021) 的信用記錄,以便只計算cDate等於 2021 的值。
$match我保持不變,我試圖在$project位中添加一個$cond

Customer.aggregate([
  {
    $match: {
      credits: {
        $elemMatch: {
          cDate: {
            $gte: ISODate("2021-01-01"),
            $lte: ISODate("2021-12-31"),
          },
        },
      },
    },
  },
  {
    $project: {      
      _id: 0,
      firstname: 1,
      lastname: 1,
      total: {        
        $cond: {
          if: { credits: { cDate: { regex: "2021-" } } }, // if cDate contains 2021-
          then: { $sum: "$credits.cAmount" },             // add the cAmount
          else: { $sum: 0 }                               // else add 0
        },
      },
    },
  }
])

這個結果仍然是一樣的,所有的總數都是從所有年份計算出來的。

{"firstname": "John", "lastname": "Doe", "total": 1180},
{"firstname": "Bob", "lastname": "Smith", "total": 590}

我錯過了什么?
謝謝你的幫助。

屬性cDate為字符串值,不能按日期類型匹配,

  • $match cDate by $regex匹配"2021"
  • $reduce循環迭代credits數組,初始值為 0
  • $substr從 0 索引和 4 個字符獲取cDate的子字符串,即年份
  • $cond要檢查的是子字符串是"2021"然后$sum初始值與cAmount否則返回初始值
Customer.aggregate([
  {
    $match: {
      "credits.cDate": {
        $regex: "2021"
      }
    }
  },
  {
    $project: {
      _id: 0,
      firstname: 1,
      lastname: 1,
      total: {
        $reduce: {
          input: "$credits",
          initialValue: 0,
          in: {
            $cond: [
              {
                $eq: [
                  { $substr: ["$$this.cDate", 0, 4] },
                  "2021"
                ]
              },
              { $sum: ["$$value", "$$this.cAmount"] },
              "$$value"
            ]
          }
        }
      }
    }
  }
])

操場

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM