Skip to content

Commit e38838e

Browse files
authored
feat(NODE-3325): support 'let' option for aggregate command (#2828)
1 parent 579119f commit e38838e

File tree

4 files changed

+283
-0
lines changed

4 files changed

+283
-0
lines changed

src/operations/aggregate.ts

+6
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ export interface AggregateOptions extends CommandOperationOptions {
3535
collation?: CollationOptions;
3636
/** Add an index selection hint to an aggregation command */
3737
hint?: Hint;
38+
/** Map of parameter names and values that can be accessed using $$var (requires MongoDB 5.0). */
39+
let?: Document;
3840
out?: string;
3941
}
4042

@@ -116,6 +118,10 @@ export class AggregateOperation<T = Document> extends CommandOperation<T> {
116118
command.hint = options.hint;
117119
}
118120

121+
if (options.let) {
122+
command.let = options.let;
123+
}
124+
119125
command.cursor = options.cursor || {};
120126
if (options.batchSize && !this.hasWriteStage) {
121127
command.cursor.batchSize = options.batchSize;

test/functional/unified-spec-runner/operations.ts

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ operations.set('aggregate', async ({ entities, operation }) => {
4040
maxAwaitTimeMS: operation.arguments.maxAwaitTimeMS,
4141
collation: operation.arguments.collation,
4242
hint: operation.arguments.hint,
43+
let: operation.arguments.let,
4344
out: operation.arguments.out
4445
})
4546
.toArray();
+195
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
{
2+
"description": "aggregate-let",
3+
"schemaVersion": "1.0",
4+
"createEntities": [
5+
{
6+
"client": {
7+
"id": "client0",
8+
"observeEvents": [
9+
"commandStartedEvent"
10+
]
11+
}
12+
},
13+
{
14+
"database": {
15+
"id": "database0",
16+
"client": "client0",
17+
"databaseName": "crud-tests"
18+
}
19+
},
20+
{
21+
"collection": {
22+
"id": "collection0",
23+
"database": "database0",
24+
"collectionName": "coll0"
25+
}
26+
}
27+
],
28+
"initialData": [
29+
{
30+
"collectionName": "coll0",
31+
"databaseName": "crud-tests",
32+
"documents": [
33+
{
34+
"_id": 1
35+
}
36+
]
37+
}
38+
],
39+
"tests": [
40+
{
41+
"description": "Aggregate with let option",
42+
"runOnRequirements": [
43+
{
44+
"minServerVersion": "5.0"
45+
}
46+
],
47+
"operations": [
48+
{
49+
"name": "aggregate",
50+
"object": "collection0",
51+
"arguments": {
52+
"pipeline": [
53+
{
54+
"$match": {
55+
"$expr": {
56+
"$eq": [
57+
"$_id",
58+
"$$id"
59+
]
60+
}
61+
}
62+
},
63+
{
64+
"$project": {
65+
"_id": 0,
66+
"x": "$$x",
67+
"y": "$$y",
68+
"rand": "$$rand"
69+
}
70+
}
71+
],
72+
"let": {
73+
"id": 1,
74+
"x": "foo",
75+
"y": {
76+
"$literal": "$bar"
77+
},
78+
"rand": {
79+
"$rand": {}
80+
}
81+
}
82+
},
83+
"expectResult": [
84+
{
85+
"x": "foo",
86+
"y": "$bar",
87+
"rand": {
88+
"$$type": "double"
89+
}
90+
}
91+
]
92+
}
93+
],
94+
"expectEvents": [
95+
{
96+
"client": "client0",
97+
"events": [
98+
{
99+
"commandStartedEvent": {
100+
"command": {
101+
"aggregate": "coll0",
102+
"pipeline": [
103+
{
104+
"$match": {
105+
"$expr": {
106+
"$eq": [
107+
"$_id",
108+
"$$id"
109+
]
110+
}
111+
}
112+
},
113+
{
114+
"$project": {
115+
"_id": 0,
116+
"x": "$$x",
117+
"y": "$$y",
118+
"rand": "$$rand"
119+
}
120+
}
121+
],
122+
"let": {
123+
"id": 1,
124+
"x": "foo",
125+
"y": {
126+
"$literal": "$bar"
127+
},
128+
"rand": {
129+
"$rand": {}
130+
}
131+
}
132+
}
133+
}
134+
}
135+
]
136+
}
137+
]
138+
},
139+
{
140+
"description": "Aggregate with let option unsupported (server-side error)",
141+
"runOnRequirements": [
142+
{
143+
"minServerVersion": "2.6.0",
144+
"maxServerVersion": "4.4.99"
145+
}
146+
],
147+
"operations": [
148+
{
149+
"name": "aggregate",
150+
"object": "collection0",
151+
"arguments": {
152+
"pipeline": [
153+
{
154+
"$match": {
155+
"_id": 1
156+
}
157+
}
158+
],
159+
"let": {
160+
"x": "foo"
161+
}
162+
},
163+
"expectError": {
164+
"errorContains": "unrecognized field 'let'",
165+
"isClientError": false
166+
}
167+
}
168+
],
169+
"expectEvents": [
170+
{
171+
"client": "client0",
172+
"events": [
173+
{
174+
"commandStartedEvent": {
175+
"command": {
176+
"aggregate": "coll0",
177+
"pipeline": [
178+
{
179+
"$match": {
180+
"_id": 1
181+
}
182+
}
183+
],
184+
"let": {
185+
"x": "foo"
186+
}
187+
}
188+
}
189+
}
190+
]
191+
}
192+
]
193+
}
194+
]
195+
}
+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
description: "aggregate-let"
2+
3+
schemaVersion: "1.0"
4+
5+
createEntities:
6+
- client:
7+
id: &client0 client0
8+
observeEvents: [ commandStartedEvent ]
9+
- database:
10+
id: &database0 database0
11+
client: *client0
12+
databaseName: &database0Name crud-tests
13+
- collection:
14+
id: &collection0 collection0
15+
database: *database0
16+
collectionName: &collection0Name coll0
17+
18+
initialData: &initialData
19+
- collectionName: *collection0Name
20+
databaseName: *database0Name
21+
documents:
22+
- { _id: 1 }
23+
24+
tests:
25+
- description: "Aggregate with let option"
26+
runOnRequirements:
27+
- minServerVersion: "5.0"
28+
operations:
29+
- name: aggregate
30+
object: *collection0
31+
arguments:
32+
pipeline: &pipeline0
33+
# $match takes a query expression, so $expr is necessary to utilize
34+
# an aggregate expression context and access "let" variables.
35+
- $match: { $expr: { $eq: ["$_id", "$$id"] } }
36+
- $project: { _id: 0, x: "$$x", y: "$$y", rand: "$$rand" }
37+
# Values in "let" must be constant or closed expressions that do not
38+
# depend on document values. This test demonstrates a basic constant
39+
# value, a value wrapped with $literal (to avoid expression parsing),
40+
# and a closed expression (e.g. $rand).
41+
let: &let0
42+
id: 1
43+
x: foo
44+
y: { $literal: "$bar" }
45+
rand: { $rand: {} }
46+
expectResult:
47+
- { x: "foo", y: "$bar", rand: { $$type: "double" } }
48+
expectEvents:
49+
- client: *client0
50+
events:
51+
- commandStartedEvent:
52+
command:
53+
aggregate: *collection0Name
54+
pipeline: *pipeline0
55+
let: *let0
56+
57+
- description: "Aggregate with let option unsupported (server-side error)"
58+
runOnRequirements:
59+
- minServerVersion: "2.6.0"
60+
maxServerVersion: "4.4.99"
61+
operations:
62+
- name: aggregate
63+
object: *collection0
64+
arguments:
65+
pipeline: &pipeline1
66+
- $match: { _id: 1 }
67+
let: &let1
68+
x: foo
69+
expectError:
70+
# Older server versions may not report an error code, but the error
71+
# message is consistent between 2.6.x and 4.4.x server versions.
72+
errorContains: "unrecognized field 'let'"
73+
isClientError: false
74+
expectEvents:
75+
- client: *client0
76+
events:
77+
- commandStartedEvent:
78+
command:
79+
aggregate: *collection0Name
80+
pipeline: *pipeline1
81+
let: *let1

0 commit comments

Comments
 (0)