Files
mongo/jstests/aggregation/sources/setWindowFields/optimize.js
Zac 591928c619 SERVER-108478 JS formatted by prettier and remove clang-format (#39656)
GitOrigin-RevId: 6c8f6aded47f260aa4f7c231b17dae3302cb1e04
2025-08-21 17:27:09 +00:00

247 lines
7.3 KiB
JavaScript

/**
* Test that redundant sorts are removed/swapped.
*
* @tags: [
* assumes_unsharded_collection,
* do_not_wrap_aggregations_in_facets,
* requires_pipeline_optimization,
* # This feature flag adjusts the desugaring a bit - requesting 'outputSortKeyMetadata' from the
* # $sort stage.
* featureFlagRankFusionBasic,
* requires_fcv_81,
* ]
*/
import {aggPlanHasStage, getAggPlanStages} from "jstests/libs/query/analyze_plan.js";
// Find how many stages of the plan are 'stageName'.
function numberOfStages(explain, stageName) {
return getAggPlanStages(explain, stageName).length;
}
const coll = db[jsTestName()];
coll.drop();
assert.commandWorked(
coll.insert([
{a: {b: 3, c: 3}, b: 2, c: 1},
{a: {b: 3, c: 3}, b: 4, c: 1},
{a: {b: 1, c: 1}, b: 4, c: 1},
{a: {b: 2, c: 2}, b: 1, c: 1},
{a: {b: 1, c: 1}, b: 4, c: 1},
{a: {b: 3, c: 3}, b: 2, c: 1},
{a: {b: 2, c: 2}, b: 1, c: 1},
{a: {b: 2, c: 2}, b: 1, c: 1},
{a: {b: 2, c: 2}, b: 3, c: 1},
{a: {b: 1, c: 1}, b: 4, c: 1},
]),
);
const explain1 = coll.explain().aggregate([
{$_internalInhibitOptimization: {}},
{
$setWindowFields: {
sortBy: {a: 1, b: 1},
output: {sum: {$sum: "$c", window: {documents: ["unbounded", "current"]}}},
},
},
{$sort: {a: 1}},
]);
// Redundant $sort should be removed.
assert.eq(1, numberOfStages(explain1, "$sort"), explain1);
// We keep the more specific sort.
assert.docEq(
[{$sort: {sortKey: {a: 1, b: 1}, outputSortKeyMetadata: true}}],
getAggPlanStages(explain1, "$sort"),
explain1,
);
const explain2 = coll.explain().aggregate([
{$_internalInhibitOptimization: {}},
{
$setWindowFields: {
sortBy: {a: 1, b: 1},
output: {sum: {$sum: "$c", window: {documents: ["unbounded", "current"]}}},
},
},
{$sort: {a: -1}},
]);
// $sort is not redundant, should not be removed.
assert.eq(2, numberOfStages(explain2, "$sort"), explain2);
const explain3 = coll.explain().aggregate([
{$_internalInhibitOptimization: {}},
{
$setWindowFields: {
sortBy: {a: 1},
output: {sum: {$sum: "$c", window: {documents: ["unbounded", "current"]}}},
},
},
{$sort: {a: 1, b: -1}},
]);
// $sort should be swapped with $_internalSetWindowFields, and the extra one removed.
assert.eq(1, numberOfStages(explain3, "$sort"), explain3);
// The sort we keep should be the more specific one.
assert.docEq(
[{$sort: {sortKey: {a: 1, b: -1}, outputSortKeyMetadata: true}}],
getAggPlanStages(explain3, "$sort"),
explain3,
);
const explain4 = coll.explain().aggregate([
{$_internalInhibitOptimization: {}},
{
$setWindowFields: {
sortBy: {a: 1},
output: {a: {$sum: "$c", window: {documents: ["unbounded", "current"]}}},
},
},
{$sort: {a: 1}},
]);
// Sort field is modified, can't be swapped or removed.
assert.eq(2, numberOfStages(explain4, "$sort"), explain4);
const explain5 = coll.explain().aggregate([
{$_internalInhibitOptimization: {}},
{
$setWindowFields: {
sortBy: {a: 1},
output: {"a.b": {$sum: "$c", window: {documents: ["unbounded", "current"]}}},
},
},
{$sort: {a: 1}},
]);
// Sort field is modified, can't be swapped or removed.
assert.eq(2, numberOfStages(explain5, "$sort"), explain5);
const explain6 = coll.explain().aggregate([
{$_internalInhibitOptimization: {}},
{
$setWindowFields: {
sortBy: {a: 1},
output: {sum: {$sum: "$c", window: {documents: ["unbounded", "current"]}}},
},
},
{$sort: {a: 1}},
{$limit: 5},
]);
// $sort + $limit should not be merged.
assert(aggPlanHasStage(explain6, "$limit"), explain6);
// The $limit should not prevent us from removing the redundant $sort.
assert.eq(1, numberOfStages(explain6, "$sort"), explain6);
const explain7 = coll
.explain()
.aggregate([
{$_internalInhibitOptimization: {}},
{$setWindowFields: {partitionBy: "$a.b", output: {sum: {$sum: "$c"}}}},
{$sort: {"a.b": 1}},
]);
// Sort should be removed if sorting and partitioning on same field.
assert.eq(1, numberOfStages(explain7, "$sort"), explain7);
const explain8 = coll.explain().aggregate([
{$_internalInhibitOptimization: {}},
{
$setWindowFields: {
partitionBy: "$a.c",
sortBy: {"a.b": 1},
output: {sum: {$sum: "$c", window: {documents: ["unbounded", "current"]}}},
},
},
{$sort: {"a.b": 1}},
]);
// Sort should not be removed since primary sort field is "a.c".
assert.eq(2, numberOfStages(explain8, "$sort"), explain8);
const explain9 = coll.explain().aggregate([
{$_internalInhibitOptimization: {}},
{
$setWindowFields: {
partitionBy: "$a.c",
sortBy: {"a.b": 1},
output: {sum: {$sum: "$c", window: {documents: ["unbounded", "current"]}}},
},
},
{$sort: {"a.c": 1}},
]);
// Sort should be removed since primary sort field is "a.c".
assert.eq(1, numberOfStages(explain9, "$sort"), explain9);
// Multiple redundant sorts are dropped.
const explain10 = coll.explain().aggregate([
{$_internalInhibitOptimization: {}},
{
$setWindowFields: {
sortBy: {a: 1, b: 1, c: 1},
output: {sum: {$sum: "$c", window: {documents: ["unbounded", "current"]}}},
},
},
{$sort: {a: 1, b: 1}},
{$sort: {a: 1}},
{$sort: {a: 1, b: 1}},
]);
assert.eq(1, numberOfStages(explain10, "$sort"), explain10);
assert.docEq(
[{$sort: {sortKey: {a: 1, b: 1, c: 1}, outputSortKeyMetadata: true}}],
getAggPlanStages(explain10, "$sort"),
explain10,
);
// Multiple compatible sorts are pushed down.
const explain11 = coll.explain().aggregate([
{$_internalInhibitOptimization: {}},
{
$setWindowFields: {
sortBy: {a: 1},
output: {sum: {$sum: "$c", window: {documents: ["unbounded", "current"]}}},
},
},
{$sort: {a: 1, b: 1, c: 1}},
{$sort: {a: 1, b: 1}},
{$sort: {a: 1, b: 1, c: 1}},
]);
assert.eq(1, numberOfStages(explain11, "$sort"), explain11);
assert.docEq(
[{$sort: {sortKey: {a: 1, b: 1, c: 1}, outputSortKeyMetadata: true}}],
getAggPlanStages(explain11, "$sort"),
explain11,
);
// An incompatible $meta sort should not be dropped or pushed down.
coll.createIndex({"$**": "text"});
const explain12 = coll.explain().aggregate([
{$match: {$text: {$search: "hi"}}},
{$_internalInhibitOptimization: {}},
{
$setWindowFields: {
sortBy: {a: 1},
output: {sum: {$sum: "$c", window: {documents: ["unbounded", "current"]}}},
},
},
{$sort: {a: {$meta: "textScore"}}},
]);
assert.eq(2, numberOfStages(explain12, "$sort"), explain12);
// For now, we don't handle $meta at all: it won't be optimized even if it's compatible.
const explain13 = coll.explain().aggregate([
{$match: {$text: {$search: "hi"}}},
{$_internalInhibitOptimization: {}},
{
$setWindowFields: {
sortBy: {a: {$meta: "textScore"}},
output: {sum: {$sum: "$c", window: {documents: ["unbounded", "current"]}}},
},
},
{$sort: {a: {$meta: "textScore"}}},
]);
assert.eq(2, numberOfStages(explain13, "$sort"), explain13);