Home > database >  Aggregate monthly results from transaction data
Aggregate monthly results from transaction data

Time:10-25

I'm a newbie at MongoDB, but have a strong SQL background.

The data I'm working with is a transactions collection, to be joined with a clients collection. The transactions collection contains every single transaction placed by our clients, could in theory be multiple transactions per day.

I want to roll those transactions up to a month-end date and sum all transaction amounts (USD_Value) to get total volume, as well as count every individual transaction to get total # of transactions in a month. This then also needs to be grouped by client and a few other fields, for analytical purposes.

So far I've built this query in mongodb:

db.transactions.aggregate([
{
     $lookup:
     {
        from: 'clients',
        localField: 'client',
        foreignField: '_id',
        as: 'clients_docs'
     }
},
{
    $match:
    {
        clients_docs: { $ne: [] }
    }
},
{
     $addFields:
     {
         clients_docs:
         {
             $arrayElemAt: ["$clients_docs", 0]
         }
     }   
},
{
    $match:
    {
        $and:
        [
            { "updated_at": { $gte: ISODate("2022-01-01") } },
            { "updated_at": { $lte: ISODate("2022-01-31") } },
            
        ]
        ,"status": { $eq: "PAID" }
        ,"clients_docs.is_send_client": { $eq: true }
    }    
},
{
      $group:
      {
          _id: 
          { 
              year_month: { $dateToString: { "date": "$updated_at", "format": "%Y-%m"  } } 
              ,client_name: "$clients_docs.client_name"
              ,client_label: "$clients_docs.client_label"
              ,client_code: "$clients_docs.client_code"
              ,client_country: "$clients_docs.client_country"
              ,base_curr: "$clients_docs.client_base_currency"
              ,inv_curr: "$clients_docs.client_invoice_currency" 
              ,dest_curr: "$store.destination_currency"         
              ,total_vol: { $sum: "$USD_Value" }
              ,total_tran: { $sum: 1 }
          }
      }                 
},
{
    $limit: 10
}
])
     

This returns this result:

{
    "_id" : {
        "year_month" : "2022-01",
        "client_name" : "company A",
        "client_label" : "company A",
        "client_code" : NumberInt(0000),
        "client_country" : "BR",
        "base_curr" : "USD",
        "inv_curr" : "USD",
        "dest_curr" : "USD",
        "total_vol" : 1000.00,
        "total_tran" : 1.0
    }
}

That's the result for just one transaction, not all transactions in that month for that client, aggregated.

It seems that in my attempt to get a YYYY-MM date format, it's just converting "$updated_at" to YYYY-MM format, but then not actually grouping by that roll-up and still just returning every individual transaction. What should I do differently to get the correct results?

To me this would have been relatively straightforward to do in SQL.

CodePudding user response:

The accumulators (that generate total_vol and total_tran) should be outside of the grouping fields (_id).

Try changing your $group to:

{
      $group:
      {
          _id: 
          { 
              year_month: { $dateToString: { "date": "$updated_at", "format": "%Y-%m"  } } 
              ,client_name: "$clients_docs.client_name"
              ,client_label: "$clients_docs.client_label"
              ,client_code: "$clients_docs.client_code"
              ,client_country: "$clients_docs.client_country"
              ,base_curr: "$clients_docs.client_base_currency"
              ,inv_curr: "$clients_docs.client_invoice_currency" 
              ,dest_curr: "$store.destination_currency"                      
          },
          total_vol: { $sum: "$USD_Value" }
         ,total_tran: { $sum: 1 }
      }                 
}
  • Related