Проблема с группировкой с условной суммой в MongoDB - PullRequest
0 голосов
/ 20 февраля 2020

Я пытаюсь разделить некоторые документы в соответствии с предыдущими 6 месяцами, а затем вычислить условную сумму определенных полей, которые удовлетворяют определенным условиям. Проблема в том, что я не вижу способа сделать это менее многословно. Я в основном ищу способ итерации в течение предыдущих 6 месяцев, а затем получить условную сумму поля.

Ниже я сделал следующее:

 [
  {
    '$facet': {
      'JanuaryTotal': [
        {
          '$match': {
            'bookingDate': {
              '$gte': ISODate('2020-01-01T00:00:00.000Z'),
              '$lt': ISODate('2020-02-01T00:00:00.000Z')
            }
          }
        }, {
          '$project': {
            '_id': 0,
            'approved': {
              '$cond': [
                {
                  '$eq': [
                    '$approvalStatus', 'approved'
                  ]
                }, '$cost', 0
              ]
            },
            'pending': {
              '$cond': [
                {
                  '$eq': [
                    '$approvalStatus', 'pending'
                  ]
                }, '$cost', 0
              ]
            },
            'denied': {
              '$cond': [
                {
                  '$eq': [
                    '$approvalStatus', 'denied'
                  ]
                }, '$cost', 0
              ]
            }
          }
        }, {
          '$group': {
            '_id': null,
            'sumApproved': {
              '$sum': '$approved'
            },
            'summPending': {
              '$sum': '$pending'
            },
            'sumDenied': {
              '$sum': '$denied'
            }
          }
        }
      ]
    }
  }
]

Образец документа:

{
   "_id":"5e45b621da68610f13aa0cba",
   "type":"international",
   "booking":"2222222",
   "bookingId":"22222222",
   "chatId":"Q22222222",
   "approvalStatus":"approved",
   "pax": "2",
   "cost":"222",
   "charged":"222",
   "chargedGCT": "222.22",
   "commRate": "2",
   "commUSD":"22.22",
   "commJMD":"2222.02",
   "bookingDate": ISODate('2020-02-01T18:00:55.000+00:00),
   "tourDate": ISODate('2020-02-03T18:00:55.000+00:00'),
   "clientName":"test",
   "agent":{
      "agentName":"test",
      "agentId":{
         "$numberInt":"1"
      }
   }
}

Есть ли способ сделать итерацию за предыдущие 6 месяцев более кратким способом?

Ответы [ 2 ]

0 голосов
/ 21 февраля 2020
db.collection.aggregate([
{
  $match: {
    bookingDate: {
      $gte: ISODate("2019-09-01T00:00:00.000Z"),
      $lte: ISODate("2020-02-01T00:00:00.000Z")
    }
  }
},
{
  $group: {
    _id: {
      $month: "$bookingDate"
    },
    sumApproved: {
      $sum: { $cond: [ { $eq: ['$approvalStatus','approved']} , { $toDouble: "$cost" }, 0] }
    },
    sumPending: {
      $sum: { $cond: [ { $eq: ['$approvalStatus','pending']} , { $toDouble: "$cost" }, 0] }
    },
    sumDenied: {
      $sum: { $cond: [ { $eq: ['$approvalStatus','denied']} , { $toDouble: "$cost" }, 0 ] }
    }
  }
},
{
  $project: {
    _id: 0,
    monthNumber: "$_id",
    sumApproved: "$sumApproved",
    sumPending: "$sumPending",
    sumDenied: "$sumDenied"
  }
}
]);

https://mongoplayground.net/p/iTyRuiQc8EI

0 голосов
/ 21 февраля 2020

Вы можете попробовать запрос ниже:

db.collection.aggregate([
    /** Match docs fall under previous 6 months */
    {
        $match: {
            'bookingDate': {
                '$gte': ISODate('2019-09-01T00:00:00.000Z'),
                '$lt': ISODate('2020-02-01T00:00:00.000Z')
            }
        }
    },

    /** This project is to reduce document size by opting lesser fields - Optional if dataset size is less */
    { $project: { _id: 0, cost: { $toInt: '$cost' }, approvalStatus: 1, bookingDate: 1 } },

    /** Grouping on month & approvalStatus + cost */
    { $group: { _id: { month: { $month: "$bookingDate" }, approvalStatus: '$approvalStatus' }, cost: { $sum: '$cost' } } },

    /** Grouping on month pushing  { approvalStatus + cost } objects to data field */
    { $group: { _id: '$_id.month', data: { $push: { approvalStatus: '$_id.approvalStatus', cost: '$cost' } } } },

    /** converting month numbers to string Ex.:- 1 as 'Jan' - Optional if no need to be converted */
    {
        $project: {
            _id: 0, data: 1, month: {
                $let: {
                    vars: {
                        monthsInString: ['', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'July', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec']
                    },
                    in: {
                        $arrayElemAt: ['$$monthsInString', '$_id']
                    }
                }
            }
        }
    }
])

Тест: MongoDB-Playground

...