Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MongoDB, Multiple count (with $exists)

I have these 3 requests:

db.mycollection.count({requestA:{$exists:true}})
db.mycollection.count({requestB:{$exists:true}})
db.mycollection.count({requestC:{$exists:true}})

I'd like to make only one request... So i tried the following:

db.mycollection.aggregate( [
    { $group: {
        '_id' : { user_id: '$user_id'},
        requestA_count: { $sum: {
            $cond: [ {requestA:{'$exists':true}}, 1, 0 ]
        } },
        requestB_count: { $sum: {
            $cond: [ {requestB:{'$exists':true}}, 1, 0 ]
        } },
        requestC_count: { $sum: {
            $cond: [ {requestC:{'$exists':true}}, 1, 0 ]
        } },
    } },
    { $project: {
        _id: 0,
        user_id: '$_id.user_id',
        requestA_count: 1,
        requestB_count: 1,
        requestC_count: 1
    } }
] );

But i got the error:

"errmsg" : "exception: invalid operator '$exists'",

I guess that we cannot use $exists with $project.

Any tips about a good approach ? Thank you

like image 575
John Smith Avatar asked Jun 12 '14 10:06

John Smith


1 Answers

You had the right basic idea but $exists is a query condition so is only valid witin a $match. What you want is the $ifNull operator to essentially do the same thing:

db.mycollection.aggregate( [
    { "$group": {
        "_id" : { "user_id": "$user_id" },
        "requestA_count": { "$sum": {
            "$cond": [ { "$ifNull": ["$requestA", false] }, 1, 0 ]
        } },
        "requestB_count": { "$sum": {
            "$cond": [ { "$ifNull": ["$requestB", false] }, 1, 0 ]
        } },
        "requestC_count": { "$sum": {
            "$cond": [ { "$ifNull": ["$requestC", false] }, 1, 0 ]
        } },
    } },
    { "$project": {
        "_id": 0,
        "user_id": "$_id.user_id",
        "requestA_count": 1,
        "requestB_count": 1,
        "requestC_count": 1
    } }
] );

So the $ifNull either returns the present value of the field if it exists or the "right side" argument is returned if it does not. The returned value other than false is intrepreted as being true ( unless of course the value is actually false ).

Essentially this gives you the same functionality of logically testing for the existence of a property in the document.

like image 130
Neil Lunn Avatar answered Sep 25 '22 21:09

Neil Lunn