-
Type: Bug
-
Resolution: Fixed
-
Priority: Critical - P2
-
Affects Version/s: 3.6.0-rc2
-
Component/s: Aggregation Framework, Querying
-
None
-
Fully Compatible
-
ALL
-
Query 2017-11-13
The 3.6 stable release series adds support for $expr, a way to use the aggregation expression language within a $match predicate:
https://docs.mongodb.com/master/reference/operator/query/expr/
The query engine optimizes $expr by attempting to fully or partially convert the $expr into a MatchExpression which can then be used to generate index bounds in the query planner. However, this rewrite optimization is incorrect if the $expr expresses a match over a path that contains any array whatsoever, regardless of whether the path is dotted. Consider the following example:
> db.c.drop(); > db.c.insert({a: [1, 2, 3]}); > db.c.find({$expr: {$gt: ["$a", 4]}}); // No results. This is incorrect because the array [1, 2, 3] is considered greater than // the number 4 in the aggregation language. In fact, all arrays are considered greater // than all numbers in aggregation, since the first part of the comparison is the // canonical type. // The explain shows that the match expression {a: {$gt: 4}} has been generated by // the $expr rewrite optimization. > db.c.find({$expr: {$gt: ["$a", 4]}}).explain() { "queryPlanner" : { "plannerVersion" : 1, "namespace" : "test.c", "indexFilterSet" : false, "parsedQuery" : { "$and" : [ { "a" : { "$gt" : 4 } }, { "$expr" : { "$gt" : [ "$a", { "$const" : 4 } ] } } ] }, "winningPlan" : { "stage" : "COLLSCAN", "filter" : { "$and" : [ { "a" : { "$gt" : 4 } }, { "$expr" : { "$gt" : [ "$a", { "$const" : 4 } ] } } ] }, "direction" : "forward" }, "rejectedPlans" : [ ] }, "serverInfo" : { "host" : "storchbox", "port" : 27017, "version" : "0.0.0", "gitVersion" : "unknown" }, "ok" : 1 }
The essence of the problem is that the match language has implicit array traversal semantics whereas the aggregation expression language does not. {$gt: ["$a", 4]} and {a: {$gt: 4}} may look the same syntactically, but their meanings are not equivalent.
- is related to
-
SERVER-31760 Lookup sub-pipeline is not using index for equality match
- Closed