summaryrefslogtreecommitdiff
path: root/jstests/aggregation/use_query_sort.js
diff options
context:
space:
mode:
Diffstat (limited to 'jstests/aggregation/use_query_sort.js')
-rw-r--r--jstests/aggregation/use_query_sort.js92
1 files changed, 49 insertions, 43 deletions
diff --git a/jstests/aggregation/use_query_sort.js b/jstests/aggregation/use_query_sort.js
index 8dbbc0c41ec..ec14625e856 100644
--- a/jstests/aggregation/use_query_sort.js
+++ b/jstests/aggregation/use_query_sort.js
@@ -18,63 +18,69 @@ for (let i = 0; i < 100; ++i) {
}
assert.commandWorked(bulk.execute());
-function assertHasNonBlockingQuerySort(pipeline) {
+function assertHasNonBlockingQuerySort(pipeline, expectRejectedPlans) {
const explainOutput = coll.explain().aggregate(pipeline);
- assert(isQueryPlan(explainOutput));
- assert(!planHasStage(db, explainOutput, "SORT"),
- "Expected pipeline " + tojsononeline(pipeline) +
- " *not* to include a SORT stage in the explain output: " + tojson(explainOutput));
- assert(planHasStage(db, explainOutput, "IXSCAN"),
- "Expected pipeline " + tojsononeline(pipeline) +
- " to include an index scan in the explain output: " + tojson(explainOutput));
- assert(!hasRejectedPlans(explainOutput),
- "Expected pipeline " + tojsononeline(pipeline) +
- " not to have any rejected plans in the explain output: " + tojson(explainOutput));
+ assert(isQueryPlan(explainOutput), explainOutput);
+ assert(!planHasStage(db, explainOutput, "SORT"), explainOutput);
+ assert(planHasStage(db, explainOutput, "IXSCAN"), explainOutput);
+ assert.eq(expectRejectedPlans, hasRejectedPlans(explainOutput), explainOutput);
return explainOutput;
}
-function assertDoesNotHaveQuerySort(pipeline) {
+function assertHasBlockingQuerySort(pipeline, expectRejectedPlans) {
const explainOutput = coll.explain().aggregate(pipeline);
- assert(isAggregationPlan(explainOutput));
- assert(aggPlanHasStage(explainOutput, "$sort"),
- "Expected pipeline " + tojsononeline(pipeline) +
- " to include a $sort stage in the explain output: " + tojson(explainOutput));
- assert(!aggPlanHasStage(explainOutput, "SORT"),
- "Expected pipeline " + tojsononeline(pipeline) +
- " *not* to include a SORT stage in the explain output: " + tojson(explainOutput));
- assert(!hasRejectedPlans(explainOutput),
- "Expected pipeline " + tojsononeline(pipeline) +
- " not to have any rejected plans in the explain output: " + tojson(explainOutput));
+ assert(isQueryPlan(explainOutput), explainOutput);
+ assert(planHasStage(db, explainOutput, "SORT"), explainOutput);
+ assert.eq(expectRejectedPlans, hasRejectedPlans(explainOutput), explainOutput);
+}
+
+function assertDoesNotHaveQuerySort(pipeline, expectRejectedPlans) {
+ const explainOutput = coll.explain().aggregate(pipeline);
+ assert(isAggregationPlan(explainOutput), explainOutput);
+ assert(aggPlanHasStage(explainOutput, "$sort"), explainOutput);
+ assert(!aggPlanHasStage(explainOutput, "SORT"), explainOutput);
+ assert.eq(expectRejectedPlans, hasRejectedPlans(explainOutput), explainOutput);
return explainOutput;
}
-// Test that a sort on the _id can use the query system to provide the sort.
-assertHasNonBlockingQuerySort([{$sort: {_id: -1}}]);
-assertHasNonBlockingQuerySort([{$sort: {_id: 1}}]);
-assertHasNonBlockingQuerySort([{$match: {_id: {$gte: 50}}}, {$sort: {_id: 1}}]);
-assertHasNonBlockingQuerySort([{$match: {_id: {$gte: 50}}}, {$sort: {_id: -1}}]);
+// Test that a sort on _id can use the query system to provide the sort. Since the sort and match
+// are both on the _id field, we don't expect there to be any rejected plans.
+assertHasNonBlockingQuerySort([{$sort: {_id: -1}}], false);
+assertHasNonBlockingQuerySort([{$sort: {_id: 1}}], false);
+assertHasNonBlockingQuerySort([{$match: {_id: {$gte: 50}}}, {$sort: {_id: 1}}], false);
+assertHasNonBlockingQuerySort([{$match: {_id: {$gte: 50}}}, {$sort: {_id: -1}}], false);
-// Test that a sort on a field not in any index cannot use a query system sort, and thus still
-// has a $sort stage.
-assertDoesNotHaveQuerySort([{$sort: {x: -1}}]);
-assertDoesNotHaveQuerySort([{$sort: {x: 1}}]);
-assertDoesNotHaveQuerySort([{$match: {_id: {$gte: 50}}}, {$sort: {x: 1}}]);
+// Test that a sort on a field not in any index will use a SORT stage in the query layer. Since
+// there is no index to support the sort, we don't expect any rejected plans.
+assertHasBlockingQuerySort([{$sort: {x: -1}}], false);
+assertHasBlockingQuerySort([{$sort: {x: 1}}], false);
+assertHasBlockingQuerySort([{$match: {_id: {$gte: 50}}}, {$sort: {x: 1}}], false);
assert.commandWorked(coll.createIndex({x: 1, y: -1}));
-assertHasNonBlockingQuerySort([{$sort: {x: 1, y: -1}}]);
-assertHasNonBlockingQuerySort([{$sort: {x: 1}}]);
-assertDoesNotHaveQuerySort([{$sort: {y: 1}}]);
-assertDoesNotHaveQuerySort([{$sort: {x: 1, y: 1}}]);
+// Since there is an index to support these sorts, we expect the system to choose a non-blocking
+// sort. The only indexed plan is an index-provided sort, so we don't expect any rejected plans.
+assertHasNonBlockingQuerySort([{$sort: {x: 1, y: -1}}], false);
+assertHasNonBlockingQuerySort([{$sort: {x: 1}}], false);
-// Test that a $match on a field not present in the same index eligible to provide a sort can
-// still result in a index scan on the sort field (SERVER-7568).
-assertHasNonBlockingQuerySort([{$match: {_id: {$gte: 50}}}, {$sort: {x: 1}}]);
+// These sorts cannot be provided by an index, but it still should get pushed down to the query
+// layer. The only plan is a COLLSCAN followed by a blocking sort, so we don't expect any rejected
+// plans.
+assertHasBlockingQuerySort([{$sort: {y: 1}}], false);
+assertHasBlockingQuerySort([{$sort: {x: 1, y: 1}}], false);
-// Test that a sort on the text score does not use the query system to provide the sort, since
-// it would need to be a blocking sort, and we prefer the $sort stage to the query system's sort
-// implementation.
+// In this case, there are two possible plans: an _id index scan with a blocking SORT, or an
+// index-provided sort by scanning the {x: 1, y: -1} index. Since the _id predicate is more
+// selective, we expect the blocking SORT plan to win and there to be a rejected plan.
+assertHasBlockingQuerySort([{$match: {_id: {$gte: 90}}}, {$sort: {x: 1}}], true);
+// A query of the same shape will use a non-blocking plan if the predicate is not selective.
+assertHasNonBlockingQuerySort([{$match: {_id: {$gte: 0}}}, {$sort: {x: 1}}], true);
+
+// Meta-sort on "textScore" currently cannot be pushed down into the query layer. See SERVER-43816.
assert.commandWorked(coll.createIndex({x: "text"}));
assertDoesNotHaveQuerySort(
- [{$match: {$text: {$search: "test"}}}, {$sort: {key: {$meta: "textScore"}}}]);
+ [{$match: {$text: {$search: "test"}}}, {$sort: {key: {$meta: "textScore"}}}], false);
+
+// Meta-sort on "randVal" cannot be pushed into the query layer. See SERVER-43816.
+assertDoesNotHaveQuerySort([{$sort: {key: {$meta: "randVal"}}}], false);
}());