Details
-
Bug
-
Resolution: Fixed
-
Critical - P2
-
3.6.0-rc2
-
None
-
Fully Compatible
-
ALL
-
Query 2017-11-13
Description
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.
Attachments
Issue Links
- is related to
-
SERVER-31760 Lookup sub-pipeline is not using index for equality match
-
- Closed
-