Using $exists in a MongoDB expression
Asked Answered
R

2

15

For background, if I want to compare two fields, I can't use the following syntax (because it compares to the literal string "$lastName" rather than the contents of the $lastName field):

"$match": { "firstName": { $ne : "$lastName"} }

I have to use this:

"$match": { "$expr": { $ne : [ "$firstName", "$lastName" ] } }

If I want to test that a field exists I must use the first format:

"$match": { "fullName": { "$exists": true } }

What I think would be the correct way for expressing the $exists operator in the latter format throws an error:

db.docs.aggregate([
  {
    "$match": { "$expr": { "$exists": [ "$fullName", true ] } }
  }
])
assert: command failed: {
        "ok" : 0,
        "errmsg" : "Unrecognized expression '$exists'",
        "code" : 168,
        "codeName" : "InvalidPipelineOperator"
} : aggregate failed

Does this mean it is not possible to combine these operations, at least in some conditions? Specifically, suppose I want to find docs where either $fullName $exists OR $firstName $ne $lastName. Can that be expressed?

Rubierubiginous answered 12/7, 2018 at 17:13 Comment(1)
Possible dupe of #25497650Peterus
P
16

You will need to use the $or logical operator to do this.

{
   "$or": [
      {
         "$expr": {
            "$ne": [
               "$firstName",
               "$lastName"
            ]
         }
      },
      {
         "fullName": {
            "$exists": true
         }
      }
   ]
}

You last query failed because mongod thinks $exists is the expression you are passing the the $expr operator.

Piegari answered 12/7, 2018 at 17:56 Comment(2)
This answer is what I was looking for, which is not addressed in #25497650, so my perspective is that it is not a duplicate, but I have a bias. Thanks for the answer.Rubierubiginous
Will this be indexed?Alexandrine
C
3

You can use the $type operator to get the type of a field. For fields that are not defined, this will be "missing".

You can spot a missing field with this non-equality check:

{$ne: [{$type: "$field"}, "missing"]}

Note that fields that are present but set to null will have the type "null", so you may also need to check for that case explicitly, c.f. the handy type table in the documentation.

For your context, the full aggregation pipeline stage checking both equality between first- and last name and that a full name field exists, could be something like this:

{
  "$match": {
    "$expr": {
      "$and": [
        { "$ne": [ { "$type": "$fullName" }, "missing" ] },
        { "$ne": [ "$firstName", "$lastName" ] }
      ]
    }
  }
}
Cacophonous answered 15/2, 2023 at 10:0 Comment(2)
While this code may solve the question, including an explanation of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please edit your answer to add explanations and give an indication of what limitations and assumptions apply.Brittneybrittni
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Mathildamathilde

© 2022 - 2024 — McMap. All rights reserved.