-
Notifications
You must be signed in to change notification settings - Fork 82
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Implement $top and $bottom accumulator operators.
- Loading branch information
Showing
5 changed files
with
254 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// https://www.mongodb.com/docs/manual/reference/operator/aggregation/bottom/#mongodb-group-grp.-bottom | ||
import { Options } from "../../core"; | ||
import { AnyVal, RawObject } from "../../types"; | ||
import { $bottomN } from "./bottomN"; | ||
|
||
/** | ||
* Returns the bottom element within a group according to the specified sort order. | ||
* | ||
* @param {Array} collection The input array | ||
* @param {Object} expr The right-hand side expression value of the operator | ||
* @param {Options} options The options to use for this operation | ||
* @returns {*} | ||
*/ | ||
export function $bottom( | ||
collection: RawObject[], | ||
expr: { sortBy: Record<string, number>; output: AnyVal }, | ||
options?: Options | ||
): AnyVal[] { | ||
return $bottomN(collection, { ...expr, n: 1 }, options); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// https://www.mongodb.com/docs/manual/reference/operator/aggregation/top/#mongodb-group-grp.-top | ||
import { Options } from "../../core"; | ||
import { AnyVal, RawObject } from "../../types"; | ||
import { $topN } from "./topN"; | ||
|
||
/** | ||
* Returns the top element within a group according to the specified sort order. | ||
* | ||
* @param {Array} collection The input array | ||
* @param {Object} expr The right-hand side expression value of the operator | ||
* @param {Options} options The options to use for this operation | ||
* @returns {*} | ||
*/ | ||
export function $top( | ||
collection: RawObject[], | ||
expr: { sortBy: Record<string, number>; output: AnyVal }, | ||
options?: Options | ||
): AnyVal[] { | ||
return $topN(collection, { ...expr, n: 1 }, options); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
import * as samples from "../../support"; | ||
|
||
const docs = [ | ||
{ playerId: "PlayerA", gameId: "G1", score: 31 }, | ||
{ playerId: "PlayerB", gameId: "G1", score: 33 }, | ||
{ playerId: "PlayerC", gameId: "G1", score: 99 }, | ||
{ playerId: "PlayerD", gameId: "G1", score: 1 }, | ||
{ playerId: "PlayerA", gameId: "G2", score: 10 }, | ||
{ playerId: "PlayerB", gameId: "G2", score: 14 }, | ||
{ playerId: "PlayerC", gameId: "G2", score: 66 }, | ||
{ playerId: "PlayerD", gameId: "G2", score: 80 }, | ||
]; | ||
|
||
samples.runTestPipeline("operators/accumulator/bottom", [ | ||
{ | ||
message: "Null and Missing Values", | ||
input: [ | ||
{ playerId: "PlayerA", gameId: "G1", score: 1 }, | ||
{ playerId: "PlayerB", gameId: "G1", score: 2 }, | ||
{ playerId: "PlayerC", gameId: "G1", score: 3 }, | ||
{ playerId: "PlayerD", gameId: "G1" }, | ||
{ playerId: "PlayerE", gameId: "G1", score: null }, | ||
], | ||
pipeline: [ | ||
{ | ||
$group: { | ||
_id: "$gameId", | ||
playerId: { | ||
$bottom: { | ||
output: ["$playerId", "$score"], | ||
sortBy: { score: -1 }, | ||
}, | ||
}, | ||
}, | ||
}, | ||
], | ||
expected: [ | ||
{ | ||
_id: "G1", | ||
playerId: [["PlayerE", null]], | ||
}, | ||
], | ||
}, | ||
{ | ||
message: "Data Type Sort Ordering", | ||
input: [ | ||
{ playerId: "PlayerA", gameId: "G1", score: 1 }, | ||
{ playerId: "PlayerB", gameId: "G1", score: "2" }, | ||
{ playerId: "PlayerC", gameId: "G1", score: "" }, | ||
], | ||
pipeline: [ | ||
{ | ||
$group: { | ||
_id: "$gameId", | ||
playerId: { | ||
$bottom: { | ||
output: ["$playerId", "$score"], | ||
sortBy: { score: -1 }, | ||
}, | ||
}, | ||
}, | ||
}, | ||
], | ||
expected: [ | ||
{ | ||
_id: "G1", | ||
playerId: [["PlayerA", 1]], | ||
}, | ||
], | ||
}, | ||
|
||
{ | ||
message: "Finding the Three Lowest Score Documents Across Multiple Games", | ||
input: docs, | ||
pipeline: [ | ||
{ | ||
$group: { | ||
_id: "$gameId", | ||
playerId: { | ||
$bottom: { | ||
output: ["$playerId", "$score"], | ||
sortBy: { score: -1 }, | ||
}, | ||
}, | ||
}, | ||
}, | ||
], | ||
expected: [ | ||
{ | ||
_id: "G1", | ||
playerId: [["PlayerD", 1]], | ||
}, | ||
{ | ||
_id: "G2", | ||
playerId: [["PlayerA", 10]], | ||
}, | ||
], | ||
}, | ||
{ | ||
message: "Computing n Based on the Group Key for $group", | ||
input: docs, | ||
pipeline: [ | ||
{ | ||
$group: { | ||
_id: { gameId: "$gameId" }, | ||
gamescores: { | ||
$bottom: { | ||
output: "$score", | ||
sortBy: { score: -1 }, | ||
}, | ||
}, | ||
}, | ||
}, | ||
], | ||
expected: [ | ||
{ _id: { gameId: "G1" }, gamescores: [1] }, | ||
{ _id: { gameId: "G2" }, gamescores: [10] }, | ||
], | ||
}, | ||
]); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
import * as samples from "../../support"; | ||
|
||
const docs = [ | ||
{ playerId: "PlayerA", gameId: "G1", score: 31 }, | ||
{ playerId: "PlayerB", gameId: "G1", score: 33 }, | ||
{ playerId: "PlayerC", gameId: "G1", score: 99 }, | ||
{ playerId: "PlayerD", gameId: "G1", score: 1 }, | ||
{ playerId: "PlayerA", gameId: "G2", score: 10 }, | ||
{ playerId: "PlayerB", gameId: "G2", score: 14 }, | ||
{ playerId: "PlayerC", gameId: "G2", score: 66 }, | ||
{ playerId: "PlayerD", gameId: "G2", score: 80 }, | ||
]; | ||
samples.runTestPipeline("operators/accumulator/top", [ | ||
{ | ||
message: "Null and Missing Values", | ||
input: [ | ||
{ playerId: "PlayerA", gameId: "G1", score: 1 }, | ||
{ playerId: "PlayerB", gameId: "G1", score: 2 }, | ||
{ playerId: "PlayerC", gameId: "G1", score: 3 }, | ||
{ playerId: "PlayerD", gameId: "G1" }, | ||
{ playerId: "PlayerE", gameId: "G1", score: null }, | ||
], | ||
pipeline: [ | ||
{ | ||
$group: { | ||
_id: "$gameId", | ||
playerId: { | ||
$top: { | ||
output: ["$playerId", "$score"], | ||
sortBy: { score: 1 }, | ||
}, | ||
}, | ||
}, | ||
}, | ||
], | ||
expected: [ | ||
{ | ||
_id: "G1", | ||
playerId: [["PlayerD", undefined]], | ||
}, | ||
], | ||
}, | ||
{ | ||
message: "Data Type Sort Ordering", | ||
input: [ | ||
{ playerId: "PlayerA", gameId: "G1", score: 1 }, | ||
{ playerId: "PlayerB", gameId: "G1", score: "2" }, | ||
{ playerId: "PlayerC", gameId: "G1", score: "" }, | ||
], | ||
pipeline: [ | ||
{ | ||
$group: { | ||
_id: "$gameId", | ||
playerId: { | ||
$top: { | ||
output: ["$playerId", "$score"], | ||
sortBy: { score: -1 }, | ||
}, | ||
}, | ||
}, | ||
}, | ||
], | ||
expected: [ | ||
{ | ||
_id: "G1", | ||
playerId: [["PlayerB", "2"]], | ||
}, | ||
], | ||
}, | ||
|
||
{ | ||
message: "Find the Top Score Across Multiple Games", | ||
input: docs, | ||
pipeline: [ | ||
{ | ||
$group: { | ||
_id: "$gameId", | ||
playerId: { | ||
$top: { | ||
output: ["$playerId", "$score"], | ||
sortBy: { score: -1 }, | ||
}, | ||
}, | ||
}, | ||
}, | ||
], | ||
expected: [ | ||
{ _id: "G1", playerId: [["PlayerC", 99]] }, | ||
{ _id: "G2", playerId: [["PlayerD", 80]] }, | ||
], | ||
}, | ||
]); |