MongoDB 2.1 Aggregate Framework Sum of Array Elements matching a name

前端 未结 2 1516
别那么骄傲
别那么骄傲 2020-12-05 05:42

This is a question about the best way to add up a series of data in an array where I have to match another element. I\'m trying to use the 2.2 Aggregation framework and it\'

相关标签:
2条回答
  • 2020-12-05 05:55

    You can use the aggregation framework to get sales and profit and any other value you may be storing in your key/value pair representation.

    For your example data:

    var pipeline = [
        {
            "$unwind" : "$finance"
        },
        {
            "$group" : {
                "_id" : "$finance.k",
                "numberOf" : {
                    "$sum" : 1
                },
                "total" : {
                    "$sum" : "$finance.v.v"
                }
            }
        }
    ]
    
    R = db.tb.aggregate( pipeline );
    printjson(R);
    {
            "result" : [
                {
                    "_id" : "profit",
                    "numberOf" : 2,
                    "total" : 246246
                },
                {
                    "_id" : "sales",
                    "numberOf" : 2,
                    "total" : 468000
                }
            ],
            "ok" : 1
    }
    

    If you have additional k/v pairs then you can add a match which only passes through k values in ["sales","profit"].

    0 讨论(0)
  • 2020-12-05 05:59

    You will have to use '$unwind" to break out the values in the array, which will mean that you can't get the sum of the sales and the profit in a single aggregation command. Given that, the query itself is easy:

    var pipeline = [ 
            {"$unwind": "$finance" } ,
            {"$match": {"finance.k": "sales"} },
            { $group: 
                { _id: null,
                    numberOf: { "$sum": 1 },
                    sales: {"$sum": "$finance.v.v" }
                }
            }
        ];
    
    R = db.tb.aggregate( pipeline );
    printjson(R);
    
    {
            "result" : [
                    {
                            "_id" : null,
                            "numberOf" : 2,
                            "sales" : 236340
                    }
            ],
            "ok" : 1
    }
    

    You can run a similar query for profit, just substitute "profit" for "sales" in the "$match" operator.

    Oh, and here's the map/reduce example:

    map = function() {
        var ret = { sales: 0.0 , profit: 0.0, count: 1 };
    
        // iterate over 'finance[]' array
        this.finance.forEach( function (i) { 
            if ( i.k == "sales" ) ret.sales =  i.v.v ;
            if ( i.k == "profit" ) ret.profit =  i.v.v ;
        } );
    
        emit( 1, ret );
    }
    
    reduce = function(key, values) {
        var ret = { sales: 0.0 , profit: 0.0, count: 0 };
    
        values.forEach(function(v) {
            ret.sales += v.sales;
            ret.profit += v.profit;
            ret.count += v.count;
        });
    
        return ret;
        };
    //
    // run map/reduce
    //
    res = SOURCE.mapReduce( map, reduce );
    
    0 讨论(0)
提交回复
热议问题