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

924 lines
29 KiB
JavaScript

/**
* Test that $minMaxScaler window function output values are as expected.
* @tags: [featureFlagSearchHybridScoringFull, requires_fcv_82]
*/
const coll = db[jsTestName()];
coll.drop();
// Input documents to test against.
// The value of field "x" is what we will compute the $minMaxScaler of in these tests.
// The value of field "y" is used to test sorting docs by a field other than "_id".
let documents = [
{_id: 1, "x": -3, "y": 8, "partition": "A"},
{_id: 2, "x": 10, "y": 4, "partition": "B"},
{_id: 3, "x": 3, "y": -2, "partition": "A"},
{_id: 4, "x": 2, "y": 3, "partition": "B"},
{_id: 5, "x": -6, "y": 6, "partition": "A"},
{_id: 6, "x": 0, "y": -8, "partition": "B"},
{_id: 7, "x": 4, "y": 10, "partition": "A"},
];
assert.commandWorked(coll.insertMany(documents));
// Helper function to assert the output field of $setWindowField is as expected for different input
// queries.
// Each entry in the array specifies a test case with input args to $setWindowFields,
// and the expected output field value for each document id.
// Expected test case structure:
// let testCases = [
// {
// setWindowFieldsArgs: {
// ...
// },
// docIdToOutputFieldValue: {
// <doc_id>: <$minMaxScaler output field value>,
// ...
// }
// },
// ];
function validateTestCase(testCase) {
let results = coll.aggregate([{$setWindowFields: testCase.setWindowFieldsArgs}]).toArray();
// Check for each entry in result, the output field value is as expected
for (let result of results) {
assert(
result.relativeXValue.toFixed(2) == testCase.docIdToOutputFieldValue[result._id].toFixed(2),
`'relativeXValue' of '${result.relativeXValue.toFixed(2)}' does not match
expected value of '${testCase.docIdToOutputFieldValue[result._id].toFixed(2)}'
for doc '_id': '${result._id}', for test with setWindowFieldsArgs =
'${JSON.stringify(testCase.setWindowFieldsArgs)}'`,
);
}
}
// Document id to field value map (where input is '$x')
// for special case where the window is left and right unbounded.
// In these cases where both the left and right are unbounded, the window never slides,
// so all (non-partitioned) $minMaxScaler queries result in this expected map.
// This implies that for these ['unbounded', 'unbounded'] windows it does not matter
// if the windowing scheme is 'documents' or 'range', or what the 'sortBy' key is.
const expectedDocIdToOutputFieldValueForUnboundedQueries = {
1: 3 / 16,
2: 1,
3: 9 / 16,
4: 8 / 16,
5: 0,
6: 6 / 16,
7: 10 / 16,
};
// Tests that document based bounds queries with non-removable windows produce the correct output
// field value. Non-removable queries are those which are unbounded on the left.
function testDocumentBasedNonRemovableQueries() {
// Testing left and right unbounded windows.
validateTestCase({
setWindowFieldsArgs: {
sortBy: {_id: 1},
output: {
"relativeXValue": {$minMaxScaler: {input: "$x"}, window: {documents: ["unbounded", "unbounded"]}},
},
},
docIdToOutputFieldValue: expectedDocIdToOutputFieldValueForUnboundedQueries,
});
// Same as last case, but not specifying bounds (which default to the same as above).
validateTestCase({
setWindowFieldsArgs: {
sortBy: {_id: 1},
output: {
"relativeXValue": {$minMaxScaler: {input: "$x"}},
},
},
docIdToOutputFieldValue: expectedDocIdToOutputFieldValueForUnboundedQueries,
});
// Tests reverse sorting in unbounded case. In an unbounded case, the results should not depend
// on sorting field (so results are same as above).
validateTestCase({
setWindowFieldsArgs: {
sortBy: {_id: -1},
output: {
"relativeXValue": {$minMaxScaler: {input: "$x"}, window: {documents: ["unbounded", "unbounded"]}},
},
},
docIdToOutputFieldValue: expectedDocIdToOutputFieldValueForUnboundedQueries,
});
// Tests reverse sorting in unbounded case. In an unbounded case, the results should not depend
// on sorting field (so results are same as above).
validateTestCase({
setWindowFieldsArgs: {
sortBy: {y: -1},
output: {
"relativeXValue": {$minMaxScaler: {input: "$x"}, window: {documents: ["unbounded", "unbounded"]}},
},
},
docIdToOutputFieldValue: expectedDocIdToOutputFieldValueForUnboundedQueries,
});
// Left and right unbounded query should not depend on sorting field
// (so results are same as above).
validateTestCase({
setWindowFieldsArgs: {
sortBy: {y: 1},
output: {
"relativeXValue": {$minMaxScaler: {input: "$x"}, window: {documents: ["unbounded", "unbounded"]}},
},
},
docIdToOutputFieldValue: expectedDocIdToOutputFieldValueForUnboundedQueries,
});
// Testing right non-unbounded windows.
validateTestCase({
setWindowFieldsArgs: {
sortBy: {_id: 1},
output: {
"relativeXValue": {$minMaxScaler: {input: "$x"}, window: {documents: ["unbounded", "current"]}},
},
},
docIdToOutputFieldValue: {
1: 0,
2: 1,
3: 6 / 13,
4: 5 / 13,
5: 0,
6: 6 / 16,
7: 10 / 16,
},
});
validateTestCase({
setWindowFieldsArgs: {
sortBy: {_id: 1},
output: {
"relativeXValue": {$minMaxScaler: {input: "$x"}, window: {documents: ["unbounded", 1]}},
},
},
docIdToOutputFieldValue: {
1: 0,
2: 1,
3: 6 / 13,
4: 8 / 16,
5: 0,
6: 6 / 16,
7: 10 / 16,
},
});
validateTestCase({
setWindowFieldsArgs: {
sortBy: {_id: -1},
output: {
"relativeXValue": {$minMaxScaler: {input: "$x"}, window: {documents: ["unbounded", 1]}},
},
},
docIdToOutputFieldValue: {
1: 3 / 16, // includes all
2: 1, // includes all
3: 9 / 16, // includes [4, 0, -6, 2, 3, 10]
4: 8 / 10, // includes [4, 0, -6, 2, 3]
5: 0, // includes [4, 0, -6, 2]
6: 6 / 10, // includes [4, 0, -6]
7: 1, // includes [4, 0]
},
});
// List of documents with y sorted descending:
// {_id: 7, "x": 4, "y": 10, "partition": "A"},
// {_id: 1, "x": -3, "y": 8, "partition": "A"},
// {_id: 5, "x": -6, "y": 6, "partition": "A"},
// {_id: 2, "x": 10, "y": 4, "partition": "B"},
// {_id: 4, "x": 2, "y": 3, "partition": "B"},
// {_id: 3, "x": 3, "y": -2, "partition": "A"},
// {_id: 6, "x": 0, "y": -8, "partition": "B"},
validateTestCase({
setWindowFieldsArgs: {
sortBy: {y: -1},
output: {
"relativeXValue": {$minMaxScaler: {input: "$x"}, window: {documents: ["unbounded", 1]}},
},
},
docIdToOutputFieldValue: {
1: 3 / 10, // includes [4, -3, -6]
2: 1, // includes [4, -3, -6, 10, 2]
3: 9 / 16, // includes all
4: 1 / 2, // includes [4, -3, -6, 10, 2, 3]
5: 0, // includes [4, -3, -6, 10]
6: 3 / 8, // includes all
7: 1, // includes [4, -3]
},
});
validateTestCase(
// Previous case with scaled domain.
{
setWindowFieldsArgs: {
sortBy: {_id: 1},
output: {
"relativeXValue": {
$minMaxScaler: {input: "$x", min: 10000, max: 20000},
window: {documents: ["unbounded", 1]},
},
},
},
docIdToOutputFieldValue: {
1: 10000,
2: 20000,
3: 190000 / 13,
4: 15000,
5: 10000,
6: 13750,
7: 16250,
},
},
);
validateTestCase({
// Sort by a field 'y' instead of '_id'.
setWindowFieldsArgs: {
sortBy: {y: 1},
output: {
"relativeXValue": {$minMaxScaler: {input: "$x"}, window: {documents: ["unbounded", "current"]}},
},
},
docIdToOutputFieldValue: {
1: 3 / 16,
2: 1,
3: 1,
4: 2 / 3,
5: 0,
6: 0,
7: 10 / 16,
},
});
validateTestCase({
// Sort by a field 'y' instead of '_id'.
setWindowFieldsArgs: {
sortBy: {y: 1},
output: {
"relativeXValue": {$minMaxScaler: {input: "$x"}, window: {documents: ["unbounded", 1]}},
},
},
docIdToOutputFieldValue: {
1: 3 / 16,
2: 1,
3: 1,
4: 2 / 10,
5: 0,
6: 0,
7: 10 / 16,
},
});
// Testing other / more complex input expressions
validateTestCase(
// Testing a constant input expression.
// Every output value of the window should always be 0 for any constant,
// because we only ever add in the same value into the window.
{
setWindowFieldsArgs: {
sortBy: {y: 1},
output: {
"relativeXValue": {
$minMaxScaler: {input: {$const: 1}},
window: {documents: ["unbounded", 1]},
},
},
},
docIdToOutputFieldValue: {
1: 0,
2: 0,
3: 0,
4: 0,
5: 0,
6: 0,
7: 0,
},
},
);
validateTestCase(
// Testing a more complex input expression.
{
setWindowFieldsArgs: {
sortBy: {_id: 1},
output: {
"relativeXValue": {
$minMaxScaler: {input: {$add: ["$x", "$y"]}},
window: {documents: ["unbounded", 2]},
},
},
},
docIdToOutputFieldValue: {
1: 4 / 13,
2: 1,
3: 1 / 14,
4: 13 / 22,
5: 8 / 22,
6: 0,
7: 1,
},
},
);
// Testing partitions
validateTestCase({
setWindowFieldsArgs: {
partitionBy: "$partition",
sortBy: {_id: 1},
output: {
"relativeXValue": {$minMaxScaler: {input: "$x"}, window: {documents: ["unbounded", "unbounded"]}},
},
},
docIdToOutputFieldValue: {
1: 3 / 10,
2: 1,
3: 9 / 10,
4: 2 / 10,
5: 0,
6: 0,
7: 1,
},
});
validateTestCase({
setWindowFieldsArgs: {
partitionBy: "$partition",
sortBy: {_id: 1},
output: {
"relativeXValue": {$minMaxScaler: {input: "$x"}, window: {documents: ["unbounded", 1]}},
},
},
docIdToOutputFieldValue: {
1: 0,
2: 1,
3: 1,
4: 2 / 10,
5: 0,
6: 0,
7: 1,
},
});
}
// Tests that range based bounds queries with non-removable windows produce the correct output
// field value. Non-removable queries are those which are unbounded on the left.
function testRangeBasedNonRemovableQueries() {
// Testing left and right unbounded windows.
validateTestCase({
setWindowFieldsArgs: {
sortBy: {_id: 1},
output: {
"relativeXValue": {$minMaxScaler: {input: "$x"}, window: {range: ["unbounded", "unbounded"]}},
},
},
docIdToOutputFieldValue: expectedDocIdToOutputFieldValueForUnboundedQueries,
});
// Left and right unbounded ranges should not depend on sorting field
// (so results are same as above).
validateTestCase({
setWindowFieldsArgs: {
sortBy: {y: 1},
output: {
"relativeXValue": {$minMaxScaler: {input: "$x"}, window: {range: ["unbounded", "unbounded"]}},
},
},
docIdToOutputFieldValue: expectedDocIdToOutputFieldValueForUnboundedQueries,
});
// Testing right non-unbounded windows.
// Range based window sorted by '_id' is equivalent to document bounds sorted by '_id'
validateTestCase({
setWindowFieldsArgs: {
sortBy: {_id: 1},
output: {
"relativeXValue": {$minMaxScaler: {input: "$x"}, window: {range: ["unbounded", "current"]}},
},
},
docIdToOutputFieldValue: {
1: 0,
2: 1,
3: 6 / 13,
4: 5 / 13,
5: 0,
6: 6 / 16,
7: 10 / 16,
},
});
validateTestCase({
setWindowFieldsArgs: {
sortBy: {_id: 1},
output: {
"relativeXValue": {$minMaxScaler: {input: "$x"}, window: {range: ["unbounded", 1]}},
},
},
docIdToOutputFieldValue: {
1: 0,
2: 1,
3: 6 / 13,
4: 8 / 16,
5: 0,
6: 6 / 16,
7: 10 / 16,
},
});
// Testing left and right unbounded windows.
validateTestCase({
setWindowFieldsArgs: {
sortBy: {_id: 1},
output: {
"relativeXValue": {$minMaxScaler: {input: "$x"}, window: {range: ["unbounded", "unbounded"]}},
},
},
docIdToOutputFieldValue: expectedDocIdToOutputFieldValueForUnboundedQueries,
});
// Left and right unbounded ranges should not depend on sorting field
// (so results are same as above).
validateTestCase({
setWindowFieldsArgs: {
sortBy: {y: 1},
output: {
"relativeXValue": {$minMaxScaler: {input: "$x"}, window: {range: ["unbounded", "unbounded"]}},
},
},
docIdToOutputFieldValue: expectedDocIdToOutputFieldValueForUnboundedQueries,
});
validateTestCase(
// Previous case with scaled domain.
{
setWindowFieldsArgs: {
sortBy: {y: 1},
output: {
"relativeXValue": {
$minMaxScaler: {input: "$x", min: 10000, max: 20000},
window: {range: ["unbounded", "unbounded"]},
},
},
},
docIdToOutputFieldValue: {
1: 11875,
2: 20000,
3: 15625,
4: 15000,
5: 10000,
6: 13750,
7: 16250,
},
},
);
validateTestCase(
// Sort by a field 'y' instead of '_id'.
{
setWindowFieldsArgs: {
sortBy: {y: 1},
output: {
"relativeXValue": {$minMaxScaler: {input: "$x"}, window: {range: ["unbounded", "current"]}},
},
},
docIdToOutputFieldValue: {
1: 3 / 16,
2: 1,
3: 1,
4: 2 / 3,
5: 0,
6: 0,
7: 10 / 16,
},
},
);
validateTestCase(
// Sort by a field 'y' instead of '_id'.
{
setWindowFieldsArgs: {
sortBy: {y: 1},
output: {
"relativeXValue": {$minMaxScaler: {input: "$x"}, window: {range: ["unbounded", 5]}},
},
},
docIdToOutputFieldValue: {
1: 3 / 16,
2: 1,
3: 1,
4: 8 / 16,
5: 0,
6: 0,
7: 10 / 16,
},
},
);
// Testing other / more complex input expressions
validateTestCase(
// Testing a constant input expression.
// Every output value of the window should always be 0 for any constant,
// because we only ever add in the same value into the window.
{
setWindowFieldsArgs: {
sortBy: {y: 1},
output: {
"relativeXValue": {$minMaxScaler: {input: {$const: 1}}, window: {range: ["unbounded", 1]}},
},
},
docIdToOutputFieldValue: {
1: 0,
2: 0,
3: 0,
4: 0,
5: 0,
6: 0,
7: 0,
},
},
);
validateTestCase(
// Testing a more complex input expression.
{
setWindowFieldsArgs: {
sortBy: {y: 1},
output: {
"relativeXValue": {
$minMaxScaler: {input: {$add: ["$x", "$y"]}},
window: {range: ["unbounded", 5]},
},
},
},
docIdToOutputFieldValue: {
1: 13 / 22,
2: 1,
3: 9 / 13,
4: 13 / 22,
5: 8 / 22,
6: 0,
7: 1,
},
},
);
// Testing partitions
validateTestCase({
setWindowFieldsArgs: {
partitionBy: "$partition",
sortBy: {_id: 1},
output: {
"relativeXValue": {$minMaxScaler: {input: "$x"}, window: {range: ["unbounded", "unbounded"]}},
},
},
docIdToOutputFieldValue: {
1: 3 / 10,
2: 1,
3: 9 / 10,
4: 2 / 10,
5: 0,
6: 0,
7: 1,
},
});
validateTestCase({
setWindowFieldsArgs: {
partitionBy: "$partition",
sortBy: {y: 1},
output: {
"relativeXValue": {$minMaxScaler: {input: "$x"}, window: {range: ["unbounded", 2]}},
},
},
docIdToOutputFieldValue: {
1: 3 / 10,
2: 1,
3: 0,
4: 2 / 10,
5: 0,
6: 0,
7: 1,
},
});
}
// Tests that document based bounds queries with removable windows produce the correct output
// field value. Removable queries are those which are bounded on the left
// (some values are removed from the window).
function testDocumentBasedRemovableQueries() {
validateTestCase(
// Windows that only ever include a single document should return 0 for every
// document.
{
setWindowFieldsArgs: {
sortBy: {_id: 1},
output: {
"relativeXValue": {$minMaxScaler: {input: "$x"}, window: {documents: ["current", "current"]}},
},
},
docIdToOutputFieldValue: {
1: 0,
2: 0,
3: 0,
4: 0,
5: 0,
6: 0,
7: 0,
},
},
);
validateTestCase(
// Windows that only ever include a single document should return 0 for every
// document.
{
setWindowFieldsArgs: {
sortBy: {_id: -1},
output: {
"relativeXValue": {$minMaxScaler: {input: "$x"}, window: {documents: ["current", "current"]}},
},
},
docIdToOutputFieldValue: {
1: 0,
2: 0,
3: 0,
4: 0,
5: 0,
6: 0,
7: 0,
},
},
);
validateTestCase(
// Windows that only ever include a single document should return 0 for every
// document.
{
setWindowFieldsArgs: {
sortBy: {y: -1},
output: {
"relativeXValue": {$minMaxScaler: {input: "$x"}, window: {documents: ["current", "current"]}},
},
},
docIdToOutputFieldValue: {
1: 0,
2: 0,
3: 0,
4: 0,
5: 0,
6: 0,
7: 0,
},
},
);
validateTestCase({
setWindowFieldsArgs: {
sortBy: {_id: 1},
output: {
"relativeXValue": {$minMaxScaler: {input: "$x"}, window: {documents: ["current", "unbounded"]}},
},
},
docIdToOutputFieldValue: {
1: 3 / 16,
2: 1,
3: 9 / 10,
4: 8 / 10,
5: 0,
6: 0,
7: 0,
},
});
validateTestCase({
setWindowFieldsArgs: {
sortBy: {_id: -1},
output: {
"relativeXValue": {$minMaxScaler: {input: "$x"}, window: {documents: ["current", "unbounded"]}},
},
},
docIdToOutputFieldValue: {
1: 0, // includes [-3]
2: 1, // includes [10, -3]
3: 6 / 13, // includes [3, 10, -3]
4: 5 / 13, // includes [2, 3, 10, -3]
5: 0, // includes [-6, 2, 3, 10, -3]
6: 3 / 8, // includes [0, -6, 2, 3, 10, -3]
7: 5 / 8, // includes [4, 0, -6, 2, 3, 10, -3]
},
});
validateTestCase({
setWindowFieldsArgs: {
sortBy: {_id: -1},
output: {
"relativeXValue": {$minMaxScaler: {input: "$x"}, window: {documents: [-1, "unbounded"]}},
},
},
docIdToOutputFieldValue: {
1: 0, // includes [10, -3]
2: 1, // includes [3, 10, -3]
3: 6 / 13, // includes [2, 3, 10, -3]
4: 1 / 2, // includes [-6, 2, 3, 10, -3]
5: 0, // includes [0, -6, 2, 3, 10, -3]
6: 3 / 8, // includes [4, 0, -6, 2, 3, 10, -3]
7: 5 / 8, // includes [4, 0, -6, 2, 3, 10, -3]
},
});
// List of documents with y sorted descending:
// {_id: 7, "x": 4, "y": 10, "partition": "A"},
// {_id: 1, "x": -3, "y": 8, "partition": "A"},
// {_id: 5, "x": -6, "y": 6, "partition": "A"},
// {_id: 2, "x": 10, "y": 4, "partition": "B"},
// {_id: 4, "x": 2, "y": 3, "partition": "B"},
// {_id: 3, "x": 3, "y": -2, "partition": "A"},
// {_id: 6, "x": 0, "y": -8, "partition": "B"},
validateTestCase({
setWindowFieldsArgs: {
sortBy: {y: -1},
output: {
"relativeXValue": {$minMaxScaler: {input: "$x"}, window: {documents: ["current", "unbounded"]}},
},
},
docIdToOutputFieldValue: {
1: 3 / 16, // includes [-3, -6, 10, 2, 3, 0]
2: 1, // includes [10, 2, 3, 0]
3: 1, // includes [3, 0]
4: 2 / 3, // includes [2, 3, 0]
5: 0, // includes [-6, 10, 2, 3, 0]
6: 0, // includes [0]
7: 5 / 8, // includes all
},
});
validateTestCase({
setWindowFieldsArgs: {
sortBy: {_id: 1},
output: {
"relativeXValue": {$minMaxScaler: {input: "$x"}, window: {documents: [-2, 2]}},
},
},
docIdToOutputFieldValue: {
1: 0,
2: 1,
3: 9 / 16,
4: 8 / 16,
5: 0,
6: 6 / 10,
7: 1,
},
});
validateTestCase(
// Sort by 'y' instead of '_id'.
{
setWindowFieldsArgs: {
sortBy: {y: 1},
output: {
"relativeXValue": {
$minMaxScaler: {input: "$x"},
window: {documents: ["current", "unbounded"]},
},
},
},
docIdToOutputFieldValue: {
1: 0,
2: 1,
3: 9 / 16,
4: 8 / 16,
5: 0,
6: 6 / 16,
7: 0,
},
},
);
validateTestCase(
// Previous case with scaled domain.
{
setWindowFieldsArgs: {
sortBy: {y: 1},
output: {
"relativeXValue": {
$minMaxScaler: {input: "$x", min: 10000, max: 20000},
window: {documents: ["current", "unbounded"]},
},
},
},
docIdToOutputFieldValue: {
1: 10000,
2: 20000,
3: 15625,
4: 15000,
5: 10000,
6: 13750,
7: 10000,
},
},
);
validateTestCase(
// Testing a more complex input expression.
{
setWindowFieldsArgs: {
sortBy: {_id: 1},
output: {
"relativeXValue": {
$minMaxScaler: {input: {$add: [1, "$x"]}},
window: {documents: ["current", "unbounded"]},
},
},
},
docIdToOutputFieldValue: {
1: 3 / 16,
2: 1,
3: 9 / 10,
4: 8 / 10,
5: 0,
6: 0,
7: 0,
},
},
);
validateTestCase(
// Testing a constant input expression.
// Every output value of the window should always be 0 for any constant,
// because we only ever add in the same value into the window.
{
setWindowFieldsArgs: {
sortBy: {y: 1},
output: {
"relativeXValue": {
$minMaxScaler: {input: {$const: 1}},
window: {documents: ["current", "unbounded"]},
},
},
},
docIdToOutputFieldValue: {
1: 0,
2: 0,
3: 0,
4: 0,
5: 0,
6: 0,
7: 0,
},
},
);
validateTestCase(
// Testing partitions.
{
setWindowFieldsArgs: {
partitionBy: "$partition",
sortBy: {_id: 1},
output: {
"relativeXValue": {$minMaxScaler: {input: "$x"}, window: {documents: [-1, 2]}},
},
},
docIdToOutputFieldValue: {
1: 3 / 9,
2: 1,
3: 9 / 10,
4: 2 / 10,
5: 0,
6: 0,
7: 1,
},
},
);
}
// Tests that range based bounds queries with removable windows produce the correct output
// field value. Removable queries are those which are bounded on the left
// (some values are removed from the window).
function testRangeBasedRemovableQueries() {
validateTestCase({
setWindowFieldsArgs: {
sortBy: {_id: 1},
output: {
"relativeXValue": {$minMaxScaler: {input: "$x"}, window: {range: ["current", 2]}},
},
},
docIdToOutputFieldValue: {
1: 0,
2: 1,
3: 1,
4: 1,
5: 0,
6: 0,
7: 0,
},
});
validateTestCase(
// Sort by a field 'y' instead of '_id'.
{
setWindowFieldsArgs: {
sortBy: {y: 1},
output: {
"relativeXValue": {$minMaxScaler: {input: "$x"}, window: {range: [-5, 5]}},
},
},
docIdToOutputFieldValue: {
1: 3 / 16,
2: 1,
3: 1,
4: 8 / 16,
5: 0,
6: 0,
7: 1,
},
},
);
validateTestCase(
// Testing partitions.
{
setWindowFieldsArgs: {
partitionBy: "$partition",
sortBy: {y: 1},
output: {
"relativeXValue": {$minMaxScaler: {input: "$x"}, window: {range: [-3, 4]}},
},
},
docIdToOutputFieldValue: {
1: 3 / 10,
2: 1,
3: 0,
4: 0,
5: 0,
6: 0,
7: 1,
},
},
);
}
testDocumentBasedNonRemovableQueries();
testRangeBasedNonRemovableQueries();
testDocumentBasedRemovableQueries();
testRangeBasedRemovableQueries();