189 lines
4.5 KiB
JavaScript
189 lines
4.5 KiB
JavaScript
/**
|
|
* Test the behavior of $first.
|
|
*/
|
|
import {seedWithTickerData, testAccumAgainstGroup} from "jstests/aggregation/extras/window_function_helpers.js";
|
|
|
|
const coll = db[jsTestName()];
|
|
coll.drop();
|
|
|
|
// Create a collection of tickers and prices.
|
|
const nDocsPerTicker = 10;
|
|
seedWithTickerData(coll, nDocsPerTicker);
|
|
|
|
// Run the suite of partition and bounds tests against the $first function.
|
|
testAccumAgainstGroup(coll, "$first");
|
|
|
|
// Like most other window functions, the default window for $first is [unbounded, unbounded].
|
|
coll.drop();
|
|
assert.commandWorked(
|
|
coll.insert([
|
|
{x: 0, y: 0},
|
|
{x: 1, y: 42},
|
|
{x: 2, y: 67},
|
|
{x: 3, y: 99},
|
|
{x: 4, y: 20},
|
|
]),
|
|
);
|
|
let result = coll
|
|
.aggregate([
|
|
{
|
|
$setWindowFields: {
|
|
sortBy: {x: 1},
|
|
output: {
|
|
first: {$first: "$y"},
|
|
},
|
|
},
|
|
},
|
|
{$unset: "_id"},
|
|
])
|
|
.toArray();
|
|
assert.sameMembers(result, [
|
|
{x: 0, y: 0, first: 0},
|
|
{x: 1, y: 42, first: 0},
|
|
{x: 2, y: 67, first: 0},
|
|
{x: 3, y: 99, first: 0},
|
|
{x: 4, y: 20, first: 0},
|
|
]);
|
|
|
|
// A default value of NULL is returned if there is no first document.
|
|
coll.drop();
|
|
assert.commandWorked(
|
|
coll.insert([
|
|
{x: 1, y: 5},
|
|
{x: 2, y: 4},
|
|
{x: 3, y: 6},
|
|
{x: 4, y: 5},
|
|
]),
|
|
);
|
|
result = coll
|
|
.aggregate([
|
|
{
|
|
$setWindowFields: {
|
|
sortBy: {x: 1},
|
|
partitionBy: "$x",
|
|
output: {
|
|
first: {$first: "$y", window: {documents: [-1, -1]}},
|
|
},
|
|
},
|
|
},
|
|
{$unset: "_id"},
|
|
])
|
|
.toArray();
|
|
assert.sameMembers(result, [
|
|
{x: 1, y: 5, first: null},
|
|
{x: 2, y: 4, first: null},
|
|
{x: 3, y: 6, first: null},
|
|
{x: 4, y: 5, first: null},
|
|
]);
|
|
|
|
// Nonobject window fields cause parse errors
|
|
result = coll.runCommand({
|
|
explain: {
|
|
aggregate: coll.getName(),
|
|
cursor: {},
|
|
pipeline: [
|
|
{
|
|
$setWindowFields: {
|
|
sortBy: {x: 1},
|
|
output: {
|
|
first: {$first: "$y", window: [0, 1]},
|
|
},
|
|
},
|
|
},
|
|
],
|
|
},
|
|
});
|
|
assert.commandFailedWithCode(result, ErrorCodes.FailedToParse, "'window' field must be an object");
|
|
|
|
// A default value of NULL is returned if the expression is constant and the window is empty.
|
|
result = coll
|
|
.aggregate([
|
|
{
|
|
$setWindowFields: {
|
|
sortBy: {x: 1},
|
|
output: {
|
|
first: {$first: "VAL", window: {documents: [2, 3]}},
|
|
},
|
|
},
|
|
},
|
|
{$unset: "_id"},
|
|
])
|
|
.toArray();
|
|
assert.sameMembers(result, [
|
|
{x: 1, y: 5, first: "VAL"},
|
|
{x: 2, y: 4, first: "VAL"},
|
|
{x: 3, y: 6, first: null},
|
|
{x: 4, y: 5, first: null},
|
|
]);
|
|
|
|
result = coll
|
|
.aggregate([
|
|
{
|
|
$setWindowFields: {
|
|
sortBy: {x: 1},
|
|
output: {
|
|
first: {$first: "VAL", window: {documents: [-3, -2]}},
|
|
},
|
|
},
|
|
},
|
|
{$unset: "_id"},
|
|
])
|
|
.toArray();
|
|
assert.sameMembers(result, [
|
|
{x: 1, y: 5, first: null},
|
|
{x: 2, y: 4, first: null},
|
|
{x: 3, y: 6, first: "VAL"},
|
|
{x: 4, y: 5, first: "VAL"},
|
|
]);
|
|
|
|
// Assert NULL is returned if field is missing
|
|
coll.drop();
|
|
assert.commandWorked(
|
|
coll.insert([
|
|
{_id: 1, x: 1},
|
|
{_id: 2, x: 1, y: 3},
|
|
{_id: 3, x: 2, y: 6},
|
|
{_id: 4, x: 2, y: 5},
|
|
]),
|
|
);
|
|
result = coll
|
|
.aggregate([
|
|
{
|
|
$setWindowFields: {
|
|
sortBy: {_id: 1},
|
|
partitionBy: "$x",
|
|
output: {
|
|
first: {$first: "$y", window: {documents: [-1, 1]}},
|
|
},
|
|
},
|
|
},
|
|
])
|
|
.toArray();
|
|
assert.sameMembers(result, [
|
|
{_id: 1, x: 1, first: null},
|
|
{_id: 2, x: 1, y: 3, first: null},
|
|
{_id: 3, x: 2, y: 6, first: 6},
|
|
{_id: 4, x: 2, y: 5, first: 6},
|
|
]);
|
|
|
|
// Re-run query with unbounded window
|
|
result = coll
|
|
.aggregate([
|
|
{
|
|
$setWindowFields: {
|
|
sortBy: {_id: 1},
|
|
partitionBy: "$x",
|
|
output: {
|
|
first: {$first: "$y", window: {}},
|
|
},
|
|
},
|
|
},
|
|
])
|
|
.toArray();
|
|
assert.sameMembers(result, [
|
|
{_id: 1, x: 1, first: null},
|
|
{_id: 2, x: 1, y: 3, first: null},
|
|
{_id: 3, x: 2, y: 6, first: 6},
|
|
{_id: 4, x: 2, y: 5, first: 6},
|
|
]);
|