Files
mongo/jstests/aggregation/sources/setWindowFields/rank.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

162 lines
4.3 KiB
JavaScript

/**
* Test the rank based window functions.
*/
import {assertErrCodeAndErrMsgContains} from "jstests/aggregation/extras/utils.js";
const coll = db[jsTestName()];
const numDoc = 12;
for (let i = 0; i < numDoc; i++) {
const doc = {_id: i, double: Math.floor(i / 2)};
if (i % 4 === 1) {
doc.nullOrMissing = null;
} else if (i % 4 === 2) {
doc.nullOrMissing = [null];
} else if (i % 4 === 3) {
doc.nullOrMissing = ["abc", null];
}
coll.insert(doc);
}
let origDocs = coll.find().sort({_id: 1});
function verifyResults(results, valueFunction) {
for (let i = 0; i < results.length; i++) {
const correctDoc = valueFunction(i, Object.assign({}, origDocs[i]));
assert.eq(
correctDoc.rank,
results[i].rank,
"Got: " + tojson(results[i]) + "\nExpected: " + tojson(correctDoc) + "\n at position " + i + "\n",
);
}
}
function runRankBasedAccumulator(sortByField, exprField) {
return coll
.aggregate([
{
$setWindowFields: {sortBy: sortByField, output: {rank: exprField}},
},
])
.toArray();
}
// Rank based accumulators don't take windows.
assert.commandFailedWithCode(
coll.runCommand({
aggregate: coll.getName(),
pipeline: [
{
$setWindowFields: {
sortBy: {_id: 1},
output: {rank: {$rank: {}, window: []}},
},
},
],
cursor: {},
}),
5371601,
);
// Rank based accumulators don't take arguments.
assert.commandFailedWithCode(
coll.runCommand({
aggregate: coll.getName(),
pipeline: [
{
$setWindowFields: {
sortBy: {_id: 1},
output: {rank: {$rank: "$_id"}},
},
},
],
cursor: {},
}),
5371603,
);
// This test validates the error message displays $rank correctly.
let pipeline = [
{
$setWindowFields: {
sortBy: {_id: 1},
output: {rank: {$rank: "$_id"}},
},
},
];
assertErrCodeAndErrMsgContains(coll, pipeline, 5371603, "$rank");
// Rank based accumulators must have a sortBy.
assert.commandFailedWithCode(
coll.runCommand({
aggregate: coll.getName(),
pipeline: [
{
$setWindowFields: {
output: {rank: {$rank: {}}},
},
},
],
cursor: {},
}),
5371602,
);
// Rank based accumulators don't take windows.
assert.commandFailedWithCode(
coll.runCommand({
aggregate: coll.getName(),
pipeline: [
{
$setWindowFields: {
sortBy: {_id: 1},
output: {rank: {$rank: {}, window: {documents: [-1, 1]}}},
},
},
],
cursor: {},
}),
5371601,
);
// Check results with no ties
let result = runRankBasedAccumulator({_id: 1}, {$rank: {}});
function noTieFunc(num, baseObj) {
baseObj.rank = num + 1;
return baseObj;
}
verifyResults(result, noTieFunc);
result = runRankBasedAccumulator({_id: 1}, {$denseRank: {}});
verifyResults(result, noTieFunc);
result = runRankBasedAccumulator({_id: 1}, {$documentNumber: {}});
verifyResults(result, noTieFunc);
// Check results with ties
origDocs = coll.find().sort({double: 1});
result = runRankBasedAccumulator({double: 1}, {$rank: {}});
verifyResults(result, function (num, baseObj) {
if (num % 2 == 0) {
baseObj.rank = num + 1;
} else {
baseObj.rank = num;
}
return baseObj;
});
result = runRankBasedAccumulator({double: 1}, {$denseRank: {}});
verifyResults(result, function (num, baseObj) {
baseObj.rank = Math.floor(num / 2) + 1;
return baseObj;
});
result = runRankBasedAccumulator({double: 1}, {$documentNumber: {}});
verifyResults(result, noTieFunc);
// Check results with null or missing fields.
result = runRankBasedAccumulator({nullOrMissing: 1}, {$rank: {}});
verifyResults(result, function (num, baseObj) {
baseObj.rank = 1;
return baseObj;
});
result = runRankBasedAccumulator({nullOrMissing: 1}, {$denseRank: {}});
verifyResults(result, function (num, baseObj) {
baseObj.rank = 1;
return baseObj;
});