I have a hard time believing this question hasn\'t been asked and answered somewhere already, but I can\'t find any trace of it.
I have a MongoDB aggregation query t
I solved the same problem just last night, this way:
> db.test.aggregate({$group:{_id:{$gt:["$field", null]}, count:{$sum:1}}})
{ "_id" : true, "count" : 2 }
{ "_id" : false, "count" : 2 }
See http://docs.mongodb.org/manual/reference/bson-types/#bson-types-comparison-order for a full explanation of how this works.
I solved it with checking for undefined
$ne : [$var_to_check, undefined]
or
$ne: [ { $type : "$var_to_check"}, 'missing'] }
This returns true if the var is defined
{'$project': {
'field_exists': {'$or': [
{'$eq': ['$field', null]},
{'$gt': ['$field', null]},
]},
}}
$exists
means that the field exists, even if it is null
or any other empty value. That is why all the answers on this page are incorrect.
Let's test a bit. Check this:
// Let's take any collection that have docs
db.getCollection('collection').aggregate([
// Get arbitrary doc, no matter which, we won't use it
{"$limit": 1},
// Project our own fields (just create them with $literal)
{'$project': {
'_id': 0,
'null_field': {'$literal': null},
'not_null_field': {'$literal': {}},
}},
])
We'll get this:
{
"null_field" : null,
"not_null_field" : {}
}
Then let's clarify which fields exist in this doc:
Okay, it's time to test project stage I've mentioned above. Let's add it for every field we're interested in:
{'$project': {
'null_field_exists': {'$or': [
{'$eq': ['$null_field', null]},
{'$gt': ['$null_field', null]},
]},
'not_null_field_exists': {'$or': [
{'$eq': ['$not_null_field', null]},
{'$gt': ['$not_null_field', null]},
]},
'non_existent_field_exists': {'$or': [
{'$eq': ['$non_existent_field', null]},
{'$gt': ['$non_existent_field', null]},
]},
}},
What we get is:
{
"null_field_exists" : true,
"not_null_field_exists" : true,
"non_existent_field_exists" : false
}
Correct!
And a small note: we use null
for comparing because it is the smallest value at least valuable (smaller is just the non-existence).
Dunno how it was but now in 2019 there is clean solution. In aggregation pipeline do this
$match: {"my_field": {$ne: null}}
Nice thing is in my lang 'ne' means not :)
The $exists operator is a "query" operator, so it is used basically to "filter" results rather than identify a logical condition.
As a "logical" operator the aggregation framework supports the $ifNull operator. This returns the field value where it exists or the alternate supplied value where it does not or otherwise evaluates to null
db.test.aggregate([
{ "$group": {
"_id": { "$ifNull": [ "$field", false ] },
"count": { "$sum": 1 }
}}
])
But of course, even that is not a "true/false" comparison, so unless you actually want to return the actual value of the field where it is present, then you are probably better off with a $cond statement much like you have:
db.test.aggregate([
{ "$group": {
"_id": { "$cond": [{ "$eq": [ "$field", null ] }, true, false ] },
"count": { "$sum": 1 }
}}
])
Where $ifNull can be very useful is in replacing not existent array fields that would otherwise cause an error using $unwind
. You can then do something like return a single element or empty array so this does not cause problems in the rest of your pipeline processing.
My answer is:
{$match:{
$and:[{
name:{
$exists:true
}
}, {
$expr:{
$eq:["$$id", "$_id"]
}
}]
}}
I use this in lookup, on my pipeline stage. This post 2 rules the first one, name must exist. And the second thing is the relation between these 2 collection. I Am sure u can modify this for your question.