I'm using a sharded replica set. Have one large collection with the following index:
{
"shop" : 1,
"email" : 1
}
I'm trying to find the best way of querying each element one by one:
db.user.explain('executionStats').find({shop:151, email:{$exists:true}}, {limit:1}))
and the results are the following.
My questions are: Is the query using the index? If yes, how can I read from this explain result?
Second: is better to use this query, loop the cursor, then query again
.find({shop:151, email:{$exists:true}}, {limit:100}))
or
.findOne({shop:151, email:{$exists:true}}))
in a continuous loop?
{
"queryPlanner" : {
"plannerVersion" : NumberInt(1),
"namespace" : "vt4users.user",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [
{
"shop" : {
"$eq" : NumberInt(151)
}
},
{
"email" : {
"$exists" : true
}
}
]
},
"winningPlan" : {
"stage" : "PROJECTION",
"transformBy" : {
"limit" : NumberInt(1)
},
"inputStage" : {
"stage" : "FETCH",
"filter" : {
"email" : {
"$exists" : true
}
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"shop" : NumberInt(1),
"email" : NumberInt(1)
},
"indexName" : "shop_1_email_1",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : true,
"isPartial" : false,
"indexVersion" : NumberInt(1),
"direction" : "forward",
"indexBounds" : {
"shop" : [
"[151.0, 151.0]"
],
"email" : [
"[MinKey, MaxKey]"
]
}
}
}
},
"rejectedPlans" : [
]
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : NumberInt(3),
"executionTimeMillis" : NumberInt(0),
"totalKeysExamined" : NumberInt(3),
"totalDocsExamined" : NumberInt(3),
"executionStages" : {
"stage" : "PROJECTION",
"nReturned" : NumberInt(3),
"executionTimeMillisEstimate" : NumberInt(0),
"works" : NumberInt(4),
"advanced" : NumberInt(3),
"needTime" : NumberInt(0),
"needYield" : NumberInt(0),
"saveState" : NumberInt(0),
"restoreState" : NumberInt(0),
"isEOF" : NumberInt(1),
"invalidates" : NumberInt(0),
"transformBy" : {
"limit" : NumberInt(1)
},
"inputStage" : {
"stage" : "FETCH",
"filter" : {
"email" : {
"$exists" : true
}
},
"nReturned" : NumberInt(3),
"executionTimeMillisEstimate" : NumberInt(0),
"works" : NumberInt(4),
"advanced" : NumberInt(3),
"needTime" : NumberInt(0),
"needYield" : NumberInt(0),
"saveState" : NumberInt(0),
"restoreState" : NumberInt(0),
"isEOF" : NumberInt(1),
"invalidates" : NumberInt(0),
"docsExamined" : NumberInt(3),
"alreadyHasObj" : NumberInt(0),
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : NumberInt(3),
"executionTimeMillisEstimate" : NumberInt(0),
"works" : NumberInt(4),
"advanced" : NumberInt(3),
"needTime" : NumberInt(0),
"needYield" : NumberInt(0),
"saveState" : NumberInt(0),
"restoreState" : NumberInt(0),
"isEOF" : NumberInt(1),
"invalidates" : NumberInt(0),
"keyPattern" : {
"shop" : NumberInt(1),
"email" : NumberInt(1)
},
"indexName" : "shop_1_email_1",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : true,
"isPartial" : false,
"indexVersion" : NumberInt(1),
"direction" : "forward",
"indexBounds" : {
"shop" : [
"[151.0, 151.0]"
],
"email" : [
"[MinKey, MaxKey]"
]
},
"keysExamined" : NumberInt(3),
"dupsTested" : NumberInt(0),
"dupsDropped" : NumberInt(0),
"seenInvalidated" : NumberInt(0)
}
}
}
},
"serverInfo" : {
"host" : "host",
"port" : NumberInt(27017),
"version" : "3.2.11",
"gitVersion" : "009580ad490190ba33d1c6253ebd8d91808923e4"
},
"ok" : NumberInt(1)
}
Your query is using the index. You can see that in the inputStage
"stage" : "IXSCAN"
You can check it in the docs to better understand its meaning.
Regarding your second question, if you want to fetch all results, looping with findOne is NOT better (performance wise) than doing the query normally.