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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With