redexp
redexp

Reputation: 5075

Mongo: How to count how many values in fields?

I have collection

[
    {
        data: {
            height: 1,
            width:  2
        }
    },{
        data: {
            height: 3,
            width:  2
        }
    },{
        data: {
            height: 3,
            width:  1
        }
    }
]

How can I count how many 1's and 3's in data.height and 1's and 2's in data.width? Basically I need result like

{
    data: {
        haight: {
            "1": 1,
            "3": 2
        },
        width:  {
            "1": 1,
            "2": 2
        }
    }
}

Thanks

Upvotes: 1

Views: 108

Answers (2)

vinipsmaker
vinipsmaker

Reputation: 2397

How can I count how many 1's and 3's in data.height and 1's and 2's in data.width?

It's possible to aggregate each value individually (as show in other answers). Alternatively, you can aggregate both values with a single command:

db.test.aggregate({$group: {_id: "$data.height", width: {$push: "$data.width"}, heightCount: {$sum: 1}}},
    {$project: {height: {id: "$_id", count: "$heightCount"}, width: 1}},
    {$unwind: "$width"},
    {$group: {_id: "$width", widthCount: {$sum: 1}, height: {$addToSet: "$height"}}},
    {$unwind: "$height"},
    {$group: {_id: null, width: {$addToSet: {id: "$_id", count: "$widthCount"}}, height: {$addToSet: "$height"}}})

How can I count how many 1's and 3's in data.height and 1's and 2's in data.width?

If you only want to aggregate 1's and 3's in data.height and 1's and 2's in data.width, then you can put the following command at the beginning of the pipeline:

{$match: {$and: [{$or: [{"data.width": 1}, {"data.width": 2}]}, {$or: [{"data.height": 1}, {"data.height": 3}]}]}}

Upvotes: 0

redexp
redexp

Reputation: 5075

Well for now I got what I need with mapReduce and it's "scope" parameter

db.myCollection.mapReduce(
    function(){
        if( this.data.height in res.data.height === false ) res.data.height[this.data.height] = 0;
        if( this.data.width in res.data.width === false ) res.data.width[this.data.width] = 0;

        res.data.height[this.data.height]++;
        res.data.width[this.data.width]++;

        emit('id', 1);
    },
    function(){
        return res;
    },
    {
        out: {inline: 1},
        scope: {
            res: {
                data:{
                    height: {},
                    width:  {}
                }
            }
        }
    }
)

Upvotes: 1

Related Questions