-
Type: Bug
-
Resolution: Done
-
Priority: Major - P3
-
Affects Version/s: 2.6.0
-
Component/s: Querying
-
None
-
Environment:> db.serverBuildInfo()
{
"version" : "2.6.0",
"gitVersion" : "1c1c76aeca21c5983dc178920f5052c298db616c",
"OpenSSLVersion" : "",
"sysInfo" : "Darwin mci-osx108-8.build.10gen.cc 12.5.0 Darwin Kernel Version 12.5.0: Sun Sep 29 13:33:47 PDT 2013; root:xnu-2050.48.12~1/RELEASE_X86_64 x86_64 BOOST_LIB_VERSION=1_49",
"loaderFlags" : "-fPIC -pthread -Wl,-bind_at_load -mmacosx-version-min=10.6",
"compilerFlags" : "-Wnon-virtual-dtor -Woverloaded-virtual -fPIC -fno-strict-aliasing -ggdb -pthread -Wall -Wsign-compare -Wno-unknown-pragmas -Winvalid-pch -Werror -pipe -O3 -Wno-unused-function -Wno-deprecated-declarations -mmacosx-version-min=10.6",
"allocator" : "system",
"versionArray" : [
2,
6,
0,
0
],
"javascriptEngine" : "V8",
"bits" : 64,
"debug" : false,
"maxBsonObjectSize" : 16777216,
"ok" : 1
}> db.serverBuildInfo() { "version" : "2.6.0", "gitVersion" : "1c1c76aeca21c5983dc178920f5052c298db616c", "OpenSSLVersion" : "", "sysInfo" : "Darwin mci-osx108-8.build.10gen.cc 12.5.0 Darwin Kernel Version 12.5.0: Sun Sep 29 13:33:47 PDT 2013; root:xnu-2050.48.12~1/RELEASE_X86_64 x86_64 BOOST_LIB_VERSION=1_49", "loaderFlags" : "-fPIC -pthread -Wl,-bind_at_load -mmacosx-version-min=10.6", "compilerFlags" : "-Wnon-virtual-dtor -Woverloaded-virtual -fPIC -fno-strict-aliasing -ggdb -pthread -Wall -Wsign-compare -Wno-unknown-pragmas -Winvalid-pch -Werror -pipe -O3 -Wno-unused-function -Wno-deprecated-declarations -mmacosx-version-min=10.6", "allocator" : "system", "versionArray" : [ 2, 6, 0, 0 ], "javascriptEngine" : "V8", "bits" : 64, "debug" : false, "maxBsonObjectSize" : 16777216, "ok" : 1 }
-
ALL
-
ISSUE SUMMARY
By definition, a negated $elemMatch value should return all results for which the field is not an array. This behavior is incorrect in 2.6.0 if the field is indexed.
USER IMPACT
Users may be getting unexpected results with indexed negated $elemMatch queries. Additionally, in SERVER-1475, a work-around to detect whether or not a field is an array was suggested using $elemMatch. This work-around no longer works in 2.6.0, due to the above bug.
WORKAROUNDS
None
RESOLUTION
Prevent negated $elemMatch values to use an index scan.
AFFECTED VERSIONS
Version 2.6.0 is affected by this bug.
PATCHES
The patch is included in the 2.6.1 production release.
Original description
A negated $elemMatch value should return all results for which the field is not an array. This behavior is incorrect in 2.6.0 if the field is indexed:
> t.drop() > t.ensureIndex({a: 1}) > t.save({a: 2}) > t.save({a: [1, 2, 3]}) > t.find() { "_id" : ObjectId("534bfa1a99d4c7138703741f"), "a" : 2 } { "_id" : ObjectId("534bfa2099d4c71387037420"), "a" : [ 1, 2, 3 ] } > t.find({a: {$elemMatch: {$gt: 1}}}) { "_id" : ObjectId("534bfa2099d4c71387037420"), "a" : [ 1, 2, 3 ] } // this is the expected result > t.find({a: {$not: {$elemMatch: {$gt: 1}}}}) // this returns no results, but should return doc {a: 2} > t.dropIndexes() > t.find({a: {$not: {$elemMatch: {$gt: 1}}}}) { "_id" : ObjectId("534bfa1a99d4c7138703741f"), "a" : 2 } // correct result without the index
Original description:
In
SERVER-1475, a nice $type work-around to detect whether or not a field is an array was suggested using $elemMatch.
I much prefer that approach over the now suggested route via $where, which I suspect to be very, very slow.
Bizzarrely, as of 2.6.0 $elemMatch seems to be broken in combination with the "_id" field, other fields do not appear to be affected.