I created a test MongoDB collection "sampleCollection" with documents which looks like:
"_id" : ObjectId("510929e041cb2179b41ace1c"),
"stringField" : "Random string0",
"longField" : NumberLong(886)
and has index on field "stringField". When I execute
db.sampleCollection.find({"stringField":"Random string0"}).explain()
everything is ok:
"cursor" : "BtreeCursor stringField_1",
"isMultiKey" : false,
"n" : 2,
"nscannedObjects" : 2,
"nscanned" : 2,
"nscannedObjectsAllPlans" : 2,
"nscannedAllPlans" : 2,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0,
"indexBounds" : {
"stringField" : [
[
"Random string0",
"Random string0"
]
]
}
but
db.sampleCollection.find({$query:{"stringField":"Random string0"}}).explain()
gets me
"cursor" : "BasicCursor",
"isMultiKey" : false,
"n" : 0,
"nscannedObjects" : 4,
"nscanned" : 4,
"nscannedObjectsAllPlans" : 4,
"nscannedAllPlans" : 4,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0,
"indexBounds" : {
}
This is not looks like a problem, but I'm using org.springframework.data.mongodb framework in production and usage of query constructions is an only way to write repositories. And thus I have a db which completely ignores indexed data.
Is it correct? Or I misunderstood something?
MongoDB uses indexing in order to make the query processing more efficient. If there is no indexing, then the MongoDB must scan every document in the collection and retrieve only those documents that match the query.
Hashed Indexes To support hash based sharding, MongoDB provides a hashed index type, which indexes the hash of the value of a field. These indexes have a more random distribution of values along their range, but only support equality matches and cannot support range-based queries.
For comparison of different BSON type values, see the specified BSON comparison order. If the field holds an array, then the $in operator selects the documents whose field holds an array that contains at least one element that matches a value in the specified array (for example, <value1> , <value2> , and so on).
MongoDB provides text indexes to support text search queries on string content. Text indexes can include any field whose value is a string or an array of string elements. A collection can only have one text search index, but that index can cover multiple fields.
That was funny i cannot decide to say it is a bug or not it is up to you:
There are two available syntax: http://docs.mongodb.org/manual/reference/operator/query/
When you using:
db.collection.find( { age : 25 } )
also will
db.collection.find( { age : 25 } ).explain()
db.collection.find( { age : 25 } ).hint(someindex)
work fine.
When you using your solution (the other syntax):
db.collection.find( { $query: { age : 25 } } )
the output of
db.sampleCollection.find({$query:{"stringField":"Random string0"}}).explain()
Will show like the query not using the index
if you also use .hint for the index it will omit the result. :) (That is i do not really understand)
Fortunately there is another syntax for these operations too: you can use:
db.sampleCollection.find({$query:{"stringField":"Random string0"}, $explain:1})
it will have the right output and showed for me the usage of the index. Also there is similar syntax for $hint.
You can check the documentation here: http://docs.mongodb.org/manual/reference/meta-query-operators/
I found this really interesting so i turned on the profiler:
i made a test collection (queryTst) with around 250k docs each with only _id and an age field in the structure with an index on age.
For this query:
db.queryTst.find({$query:{"age":16},$explain:1})
i got:
{
"cursor" : "BtreeCursor age_1",
"isMultiKey" : false,
"n" : 2,
"nscannedObjects" : 2,
"nscanned" : 2,
"nscannedObjectsAllPlans" : 2,
"nscannedAllPlans" : 2,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0,
"indexBounds" : {
"age" : [
[
16,
16
]
]
},
"allPlans" : [
{
"cursor" : "BtreeCursor age_1",
"n" : 2,
"nscannedObjects" : 2,
"nscanned" : 2,
"indexBounds" : {
"age" : [
[
16,
16
]
]
}
}
],
"oldPlan" : {
"cursor" : "BtreeCursor age_1",
"indexBounds" : {
"age" : [
[
16,
16
]
]
}
},
"server" : ""
}
for this:
db.queryTst.find({$query:{"age":16},$explain:1}).explain()
i got:
"cursor" : "BasicCursor",
"isMultiKey" : false,
"n" : 0,
"nscannedObjects" : 250011,
"nscanned" : 250011,
"nscannedObjectsAllPlans" : 250011,
"nscannedAllPlans" : 250011,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 103,
"indexBounds" : {
},
in the profiler log: for the first
{
"ts" : ISODate("2013-01-30T20:35:40.526Z"),
"op" : "query",
"ns" : "test.queryTst",
"query" : {
"$query" : {
"age" : 16
},
"$explain" : 1
},
"ntoreturn" : 0,
"ntoskip" : 0,
"nscanned" : 2,
"keyUpdates" : 0,
"numYield" : 0,
"lockStats" : {
"timeLockedMicros" : {
"r" : NumberLong(368),
"w" : NumberLong(0)
},
"timeAcquiringMicros" : {
"r" : NumberLong(8),
"w" : NumberLong(5)
}
},
"nreturned" : 1,
"responseLength" : 567,
"millis" : 0,
"client" : "127.0.0.1",
"user" : ""
}
for the second:
{
"ts" : ISODate("2013-01-30T20:35:47.715Z"),
"op" : "query",
"ns" : "test.queryTst",
"query" : {
"query" : {
"$query" : {
"age" : 16
},
"$explain" : 1
},
"$explain" : true
},
"ntoreturn" : 0,
"ntoskip" : 0,
"nscanned" : 250011,
"keyUpdates" : 0,
"numYield" : 0,
"lockStats" : {
"timeLockedMicros" : {
"r" : NumberLong(104092),
"w" : NumberLong(0)
},
"timeAcquiringMicros" : {
"r" : NumberLong(13),
"w" : NumberLong(5)
}
},
"nreturned" : 1,
"responseLength" : 373,
"millis" : 104,
"client" : "127.0.0.1",
"user" : ""
}
which somehow means to me that is the explain() cause the table scan in the mixed syntax.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With