0

I have a collection of persons whose schema looks like the collection of following documents.

    Document: {

    name:
    age:
    educations:[{
title:xyz,
passed_year:2005,
univercity:abc},
{
title:asd
passed_year:2007,
univercity:mno
}],
current_city:ghi
}

Now I wanna show all the persons who has not done xyz education from abc university in year 2005.

I think two possible queries for this need but not sure which one to use as both of them are giving me the output

Query 1:

db.persons.find({"education":{$ne:{$elemMatch:{"title":"xyz","passed_year":2005,"univercity":"abc"}}}})

Query 2:

db.persons.find({"education":{$not:{$elemMatch:{"title":"xyz","passed_year":2005,"univercity":"abc"}}}})

I'm quite confused about operator $ne and $not, which one should I use with $elemMatch as both of them are giving me the output.

1 Answer 1

1

Given this $elemMatch: {"title":"xyz","passed_year":2005,"univercity":"abc"} I think you want to exclude any documents which contain an sub document in the educations array which contains all of these pairs:

  • "title" : "xyz"
  • "passed_year" : 2005
  • "univercity" : "abc"

This query will achieve that:

db.persons.find({
    "educations": {
        $not: {
            $elemMatch:{"title": "xyz", "passed_year": 2005, "univercity": "abc"}
         }
     }
})

In your question you wrote:

both of them are giving me the output

I suspect this is because your query is specifying education whereas the correct attribute name is educations. By specifying education you are adding a predicate which cannot be evaluated since it references a non existent document attribute so regardless of whether that predicate uses $ne or $not it will simply not be applied.

In answer to the question of which operator to use: $not or $ne: if you run the above query with .explain(true) you'll notice that the parsed query produced by Mongo is very different for each of these operators.

  • Using $ne

    "parsedQuery" : {
        "$not" : {
            "educations" : {
                "$eq" : {
                    "$elemMatch" : {
                        "title" : "xyz",
                        "passed_year" : 2005,
                        "univercity" : "abc"
                    }
                }
            }
        }
    }
    
  • Using $not:

    "parsedQuery" : {
        "$not" : {
            "educations" : {
                "$elemMatch" : {
                    "$and" : [ 
                        {
                            "passed_year" : {
                                "$eq" : 2005
                            }
                        }, 
                        {
                            "title" : {
                                "$eq" : "xyz"
                            }
                        }, 
                        {
                            "univercity" : {
                                "$eq" : "abc"
                            }
                        }
                    ]
                }
            }
        }
    }
    

So, it looks like use of $ne causes Mongo to do something like this psuedo code ...

not educations equalTo "$elemMatch" : {"title" : "xyz", "passed_year" : 2005, "univercity" : "abc"}

... i.e. it treats the elemMatch clause as if it is the RHS of an equality operation whereas use of $not causes Mongo to actually evaluate the elemMatch clause.

Sign up to request clarification or add additional context in comments.

2 Comments

thank you @glitch for correcting me but I would like to ask one more question, why did you specifically choose $not operator in your query and why not $ne? Although you are correct and your query is giving me the correct answer still, somehow I felt like it's obvious that $ne should have been correct operator.
I've updated the answer to explain the difference between Mongo's handling of $ne and $not. Hope that helps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.