From a long time I had a doubt that $exists makes the query inefficient, but I was not confident enough to conclude any points soon. Today I observed something which made me confident to not use $exists going forward in my queries until it is extremely (I mean extremely) needed.
Here is why?
[
{
$match: {
project_id: ObjectId('XXXXXXXXXXXX'),
source: "marketing",
attempt_count: { $exists: true },
},
},
{ $project: { _id: 1 } },
]
Motive :- Get all the records from event_logs where attempt_count exists (docs which has field attempt_count: 1/2/3)
Even after giving the hint :- Query was inefficient
db["event_logs"].aggregate([
{
$match: {
project_id: ObjectId('XXXXXXXXXXXX'),
source: "marketing",
attempt_count: { $exists: true },
},
},
{ $project: { _id: 1 } },
], { hint: "project_id_1_source_1_attempt_count_1" }).explain("executionStats")
The point here is why it is checking 16k totalkeys and totalDocs while the nreturned is 9k, the ideal case should be totalkeys = totalDocs = nreturned (making it a covered query)
Solution for above issue :-
Use range $gte, $gt, $lte, $lt
I used this query:
db["event_logs"].aggregate([
{
$match: {
project_id: ObjectId('XXXXXXXXXXXX'),
source: "marketing",
attempt_count: { $gte: 1 },
},
},
{ $project: { _id: 1 } },
], { hint: "project_id_1_source_1_attempt_count_1" }).explain("executionStats")
Magic 🎉
CULPRIT:- $exists
Reason by LLM:
-
Point of
$exists: It tells us the field presence.
-> Now according to our requirement it seems to be very much perfect to use it. What if I convert $exists into something as a range?
-
In layman terms: What I have understood is that
$existsmakes your query search the needed as well as not needed docs because$existstells MongoDB cursor to check all the docs where there is noattempt_countand check all the docs where there isattempt_countexists and then it is only able to segregate between those sets of docs to give you the requirednReturned.
Proof:
- My needed docs were 9k and not 16k, but
$existsmade the query scan all 16k docs (around 8k extra).



Top comments (0)