Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongo DB Aggregate

I have a collection with entries that look like:

{"placeId" : "0b980482-ab4b-4685-95ab-ecc2dcba1837","placeName" : "B8 Göteborg","created" : ISODate("2017-04-09T14:53:01.005Z"),"debitAccount" : "1581","debitAmount" : 26.0,"creditAccount" : "3013","creditAmount" : 23.2142791748047,"taxAccount" : "2620","taxAmount" : 2.78572010993958},
{"placeId" : "0b980482-ab4b-4685-95ab-ecc2dcba1837","placeName" : "B8 Göteborg","created" : ISODate("2017-04-09T14:53:01.005Z"),"debitAccount" : "1581","debitAmount" : 26.0,"creditAccount" : "3014","creditAmount" : 53.2142791748047,"taxAccount" : "2621","taxAmount" : 5.78572010993958}

I want the output to be something like:

{
    "_id" : "B8 - Göteborg",
    "days" : [ 
        {
            "date" : "2017-03-24",
            "creditAccounts" : [ 
                {
                    "creditAccount" : "3013",
                    "creditAccountSum" : 23.214279174804
                }, 
                {
                    "creditAccount" : "3014",
                    "creditAccountSum" : 53.2142791748047,
                }, 
            ],
            "debitAccounts" : [ 
                {
                    "debitAccount" : "1581",
                    "debitAccountSum" : 52
                }
            ],
            "taxAccounts" : [ 
                {
                    "taxAccount" : "2620",
                    "taxAccountSum" : 2.78572010993958
                },
                {
                    "taxAccount" : "2621",
                    "taxAccountSum" : 5.78572010993958
                }
            ]
        }
    ]
}

That is per placeName and day have a list of all unique creditAccounts, debitAccounts, taxAccounts and their sum. I have managed to do the grouping for one of the fields and it looks like:

db.getCollection('accounting_records').aggregate([
    {$match : {...},  
    {$group: {_id: {placeName :'$placeName',year: {$substr: ['$created',0,4]},month: {$substr: ['$created',5,2]},dayOfMonth: {$substr: ['$created',8,2]},creditAccount:'$creditAccount'}, created: {$max: '$created'},records: { $addToSet: "$$ROOT" }}},
    {$sort : {created : 1}},
    {$group: {_id: {placeName :'$_id.placeName',year: '$_id.year',month: '$_id.month',dayOfMonth: '$_id.dayOfMonth'},created: {$max: '$created'}, creditAccounts:{$push :{creditAccount: '$_id.creditAccount',sum : {$sum: '$records.creditAmount'}, creditAccountName:'$records.creditAccountName'}}}},
    {$sort : {created : 1}},
    {$group : {_id : '$_id.placeName', created: {$max: '$created'}, days : {$push: {date: {$concat: ['$_id.year','-','$_id.month','-','$_id.dayOfMonth']},creditAccounts : '$creditAccounts'}}}},
    {$sort : {_id : 1}},
])

But I have no idea how to manage to do the grouping for all 3 creditAccount, taxAccount & debitAccount. Perhaps it's possible with mapReduce but haven't looked in to that since I've read performance is much worse compared to using aggregations framework.

like image 459
Frej Håkansson Avatar asked Jul 25 '26 10:07

Frej Håkansson


1 Answers

You need to `$group` each credit/debit/tax-Account/Amount and calculate sum.



db.collection.aggregate([
    {
        $group: {
            _id:{_id:"$placeName",date:{$dateToString:{format:"%Y-%m-%d" , date:"$created"}}, creditAccount:"$creditAccount" },
            creditAccountSum : {$sum: "$creditAmount"},
            remaining: {$push: {debitAccount:"$debitAccount",debitAmount:"$debitAmount",taxAccount:"$taxAccount",taxAmount:"$taxAmount"}}
        }
    },
    {$unwind: "$remaining"},
    {
        $group: {
            _id:{_id:"$_id._id",date:"$_id.date", debitAccount:"$remaining.debitAccount"},
            debitAccountSum : {$sum: "$remaining.debitAmount"},
            remaining: {$push: {creditAccount:"$_id.creditAccount",creditAccountSum:"$creditAccountSum", taxAccount:"$remaining.taxAccount",taxAmount:"$remaining.taxAmount"}}
        }
    },
    {$unwind: "$remaining"},
    {
        $group: {
            _id:{_id:"$_id._id",date:"$_id.date", taxAccount:"$remaining.taxAccount"},
            taxAccountSum : {$sum: "$remaining.taxAmount"},
            remaining: {$push :{creditAccount:"$remaining.creditAccount",creditAccountSum:"$remaining.creditAccountSum", debitAccount:"$_id.debitAccount", debitAccountSum:"$debitAccountSum"}}
        }
    },
    {$unwind: "$remaining"},
    {   
        $group : {
                _id:{_id:"$_id._id",date:"$_id.date"},
                creditAccounts:{$addToSet:{creditAccount:"$remaining.creditAccount",creditAccountSum:"$remaining.creditAccountSum"}},
                debitAccounts:{$addToSet:{debitAccount:"$remaining.debitAccount",debitAccountSum:"$remaining.debitAccountSum"}},
                taxAccounts:{$addToSet:{taxAccount:"$_id.taxAccount",taxAccountSum:"$taxAccountSum"}}      
        }
    },
    {
        $group : {
            _id : {_id:"$_id._id"},
            days : {$push: {date:"$_id.date",creditAccounts:"$creditAccounts",debitAccounts:"$debitAccounts", taxAccounts:"$taxAccounts"}}
        }
    },
    {
        $project: {
            _id:"$_id._id",
            days:"$days"
        }
    }
]).pretty()

Test data:

{"placeId" : "0b980482-ab4b-4685-95ab-ecc2dcba1837","placeName" : "B8 Göteborg","created" : ISODate("2017-04-09T14:53:01.005Z"),"debitAccount" : "1581","debitAmount" : 26.0,"creditAccount" : "3013","creditAmount" : 23.2142791748047,"taxAccount" : "2620","taxAmount" : 2.78572010993958},
{"placeId" : "0b980482-ab4b-4685-95ab-ecc2dcba1837","placeName" : "B8 Göteborg","created" : ISODate("2017-04-09T14:53:01.005Z"),"debitAccount" : "1581","debitAmount" : 26.0,"creditAccount" : "3014","creditAmount" : 53.2142791748047,"taxAccount" : "2621","taxAmount" : 5.78572010993958},
{"placeId" : "0b980482-ab4b-4685-95ab-ecc2dcba1837","placeName" : "B8 Göteborg","created" : ISODate("2017-05-09T14:53:01.005Z"),"debitAccount" : "1581","debitAmount" : 26.0,"creditAccount" : "3014","creditAmount" : 53.2142791748047,"taxAccount" : "2621","taxAmount" : 5.78572010993958}

Output:

{
    "_id" : "B8 Göteborg",
    "days" : [
        {
            "date" : "2017-04-09",
            "creditAccounts" : [
                {
                    "creditAccount" : "3014",
                    "creditAccountSum" : 53.2142791748047
                },
                {
                    "creditAccount" : "3013",
                    "creditAccountSum" : 23.2142791748047
                }
            ],
            "debitAccounts" : [
                {
                    "debitAccount" : "1581",
                    "debitAccountSum" : 52
                }
            ],
            "taxAccounts" : [
                {
                    "taxAccount" : "2621",
                    "taxAccountSum" : 5.78572010993958
                },
                {
                    "taxAccount" : "2620",
                    "taxAccountSum" : 2.78572010993958
                }
            ]
        },
        {
            "date" : "2017-05-09",
            "creditAccounts" : [
                {
                    "creditAccount" : "3014",
                    "creditAccountSum" : 108.4285583496094
                }
            ],
            "debitAccounts" : [
                {
                    "debitAccount" : "1581",
                    "debitAccountSum" : 52
                }
            ],
            "taxAccounts" : [
                {
                    "taxAccount" : "2621",
                    "taxAccountSum" : 12.57144021987916
                }
            ]
        }
    ]
}
like image 194
Ra Ka Avatar answered Jul 27 '26 04:07

Ra Ka



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!