ISSUE SUMMARY
The $where operator applies to top-level elements only, however in 2.4 the specific implementation allowed usage under a sub-field within the $elemMatch operator as an edge case. This behavior was unintentional. With the introduction of the new query engine in 2.6 the $where usage should have been removed in the $elemMatch operator. The special case of $where as the first condition was missed.
USER IMPACT
As the behavior has changed from 2.4.9 some queries relying on the $where operator in $elemMatch may no longer work and return an error instead.
WORKAROUNDS
In most cases, a rewrite of the query and replacement of $where clauses in the $elemMatch document should be possible.
RESOLUTION
Consistent rejection of the $where operator anywhere in $elemMatch queries, with a clear error message.
AFFECTED VERSIONS
Version 2.6.0 was affected by this bug.
PATCHES
The patch is included in the 2.6.1 production release.
Original description
If the first listed condition in an $elemMatch is a $where predicate, the query will not parse.
> db.version() 2.6.0-rc3 > db.foo.insert({a:[{b:1,c:2},{b:2,c:1}]}) WriteResult({ "nInserted" : 1 }) > db.foo.insert({a:[{b:1,c:1}]}) WriteResult({ "nInserted" : 1 }) > db.foo.find({a:{$elemMatch:{b:1,$where:'this.c==1;'}}}) { "_id" : ObjectId("5342e26193252aaba7ab9f74"), "a" : [ { "b" : 1, "c" : 1 } ] } > db.foo.find({a:{$elemMatch:{$where:'this.c==1;',b:1}}}) error: { "$err" : "Can't canonicalize query: BadValue unknown operator: $where", "code" : 17287 }
The query parses correctly in 2.4.9.
> db.version() 2.4.9 > db.foo.find({a:{$elemMatch:{$where:'this.c==1;',b:1}}}) { "_id" : ObjectId("5342e26193252aaba7ab9f74"), "a" : [ { "b" : 1, "c" : 1 } ] }
- is duplicated by
-
SERVER-14010 Use of $where within $elemMatch
- Closed
- is related to
-
SERVER-12439 $where in $elemMatch no longer valid in 2.5.5-pre
- Closed
- related to
-
SERVER-14892 Invalid {$elemMatch: {$where}} query causes memory leak
- Closed