In an expression ($expr), and only in an expression, I want to check the presence of a field with a navigation path.
db.haystack.aggregate(
[
{
'$match': {
'$expr':
{ 'a.b.c': { '$ne': null } },
},
},
],
);
But I receive an error FieldPath field names may not contain '.'
How can can check the presence of field in an $expr ? If some part of paths is not present, I want to reject the document.
{ a: 1 } // False
{ a: { b: 1 } } // False
{ a: { b: { c: 1 } } // True
You have two problems in your code, first because you require the usage of $expr let's understand what is $expr's possible input:
The arguments can be any valid aggregation expression. For more information, see Expressions.
So $expr receives an "aggregation expression" which is :
Expressions can include field paths, literals, system variables, expression objects, and expression operators. Expressions can be nested.
So the current input of {"a.b.c":{"$ne":null}} is none of these, in this case you want to use $ne aggregation form which is:
{ $ne: [ ... args ... ] }
Now comes the second issue, you are expecting this special query behaviour where querying null that matches both null values and missing fields at the same time. However this does not exist for the aggregation framework, just the query language.
There are many possible ways around this but here is a solution using $type
db.collection.aggregate([
{
"$match": {
"$expr": {
$ne: [
{
$type: "$a.b.c"
},
"missing"
]
}
}
},
])