1
+ import { type Connection } from '..' ;
1
2
import type { Document } from '../bson' ;
3
+ import { MongoDBResponse } from '../cmap/wire_protocol/responses' ;
2
4
import type { Collection } from '../collection' ;
3
5
import { MongoCompatibilityError , MongoInvalidArgumentError } from '../error' ;
4
6
import { ReadPreference } from '../read_preference' ;
5
- import type { Server } from '../sdam/server' ;
6
7
import type { ClientSession } from '../sessions' ;
7
8
import { formatSort , type Sort , type SortForCmd } from '../sort' ;
8
- import { type TimeoutContext } from '../timeout' ;
9
- import { decorateWithCollation , hasAtomicOperators , maxWireVersion } from '../utils' ;
9
+ import { decorateWithCollation , hasAtomicOperators } from '../utils' ;
10
10
import { type WriteConcern , type WriteConcernSettings } from '../write_concern' ;
11
- import { CommandOperation , type CommandOperationOptions } from './command' ;
11
+ import { type CommandOperationOptions , ModernizedCommandOperation } from './command' ;
12
12
import { Aspect , defineAspects } from './operation' ;
13
13
14
14
/** @public */
@@ -120,9 +120,9 @@ function configureFindAndModifyCmdBaseUpdateOpts(
120
120
}
121
121
122
122
/** @internal */
123
- export class FindAndModifyOperation extends CommandOperation < Document > {
123
+ export class FindAndModifyOperation extends ModernizedCommandOperation < Document > {
124
+ override SERVER_COMMAND_RESPONSE_TYPE = MongoDBResponse ;
124
125
override options : FindOneAndReplaceOptions | FindOneAndUpdateOptions | FindOneAndDeleteOptions ;
125
- cmdBase : FindAndModifyCmdBase ;
126
126
collection : Collection ;
127
127
query : Document ;
128
128
doc ?: Document ;
@@ -133,8 +133,26 @@ export class FindAndModifyOperation extends CommandOperation<Document> {
133
133
options : FindOneAndReplaceOptions | FindOneAndUpdateOptions | FindOneAndDeleteOptions
134
134
) {
135
135
super ( collection , options ) ;
136
- this . options = options ?? { } ;
137
- this . cmdBase = {
136
+ this . options = options ;
137
+ // force primary read preference
138
+ this . readPreference = ReadPreference . primary ;
139
+
140
+ this . collection = collection ;
141
+ this . query = query ;
142
+ }
143
+
144
+ override get commandName ( ) {
145
+ return 'findAndModify' as const ;
146
+ }
147
+
148
+ override buildCommandDocument (
149
+ _connection : Connection ,
150
+ _session ?: ClientSession
151
+ ) : Document & FindAndModifyCmdBase {
152
+ const options = this . options ;
153
+ const command : Document & FindAndModifyCmdBase = {
154
+ findAndModify : this . collection . collectionName ,
155
+ query : this . query ,
138
156
remove : false ,
139
157
new : false ,
140
158
upsert : false
@@ -144,77 +162,51 @@ export class FindAndModifyOperation extends CommandOperation<Document> {
144
162
145
163
const sort = formatSort ( options . sort ) ;
146
164
if ( sort ) {
147
- this . cmdBase . sort = sort ;
165
+ command . sort = sort ;
148
166
}
149
167
150
168
if ( options . projection ) {
151
- this . cmdBase . fields = options . projection ;
169
+ command . fields = options . projection ;
152
170
}
153
171
154
172
if ( options . maxTimeMS ) {
155
- this . cmdBase . maxTimeMS = options . maxTimeMS ;
173
+ command . maxTimeMS = options . maxTimeMS ;
156
174
}
157
175
158
176
// Decorate the findAndModify command with the write Concern
159
177
if ( options . writeConcern ) {
160
- this . cmdBase . writeConcern = options . writeConcern ;
178
+ command . writeConcern = options . writeConcern ;
161
179
}
162
180
163
181
if ( options . let ) {
164
- this . cmdBase . let = options . let ;
182
+ command . let = options . let ;
165
183
}
166
184
167
185
// we check for undefined specifically here to allow falsy values
168
186
// eslint-disable-next-line no-restricted-syntax
169
187
if ( options . comment !== undefined ) {
170
- this . cmdBase . comment = options . comment ;
188
+ command . comment = options . comment ;
171
189
}
172
190
173
- // force primary read preference
174
- this . readPreference = ReadPreference . primary ;
175
-
176
- this . collection = collection ;
177
- this . query = query ;
178
- }
179
-
180
- override get commandName ( ) {
181
- return 'findAndModify' as const ;
182
- }
183
-
184
- override async execute (
185
- server : Server ,
186
- session : ClientSession | undefined ,
187
- timeoutContext : TimeoutContext
188
- ) : Promise < Document > {
189
- const coll = this . collection ;
190
- const query = this . query ;
191
- const options = { ...this . options , ...this . bsonOptions } ;
192
-
193
- // Create findAndModify command object
194
- const cmd : Document = {
195
- findAndModify : coll . collectionName ,
196
- query : query ,
197
- ...this . cmdBase
198
- } ;
199
-
200
- decorateWithCollation ( cmd , coll , options ) ;
191
+ decorateWithCollation ( command , this . collection , options ) ;
201
192
202
193
if ( options . hint ) {
203
- // TODO: once this method becomes a CommandOperation we will have the server
204
- // in place to check.
205
194
const unacknowledgedWrite = this . writeConcern ?. w === 0 ;
206
- if ( unacknowledgedWrite || maxWireVersion ( server ) < 8 ) {
195
+ if ( unacknowledgedWrite ) {
207
196
throw new MongoCompatibilityError (
208
197
'The current topology does not support a hint on findAndModify commands'
209
198
) ;
210
199
}
211
200
212
- cmd . hint = options . hint ;
201
+ command . hint = options . hint ;
213
202
}
214
203
215
- // Execute the command
216
- const result = await super . executeCommand ( server , session , cmd , timeoutContext ) ;
217
- return options . includeResultMetadata ? result : ( result . value ?? null ) ;
204
+ return command ;
205
+ }
206
+
207
+ override handleOk ( response : InstanceType < typeof this . SERVER_COMMAND_RESPONSE_TYPE > ) : Document {
208
+ const result = super . handleOk ( response ) ;
209
+ return this . options . includeResultMetadata ? result : ( result . value ?? null ) ;
218
210
}
219
211
}
220
212
@@ -227,12 +219,21 @@ export class FindOneAndDeleteOperation extends FindAndModifyOperation {
227
219
}
228
220
229
221
super ( collection , filter , options ) ;
230
- this . cmdBase . remove = true ;
222
+ }
223
+
224
+ override buildCommandDocument (
225
+ connection : Connection ,
226
+ session ?: ClientSession
227
+ ) : Document & FindAndModifyCmdBase {
228
+ const document = super . buildCommandDocument ( connection , session ) ;
229
+ document . remove = true ;
230
+ return document ;
231
231
}
232
232
}
233
233
234
234
/** @internal */
235
235
export class FindOneAndReplaceOperation extends FindAndModifyOperation {
236
+ private replacement : Document ;
236
237
constructor (
237
238
collection : Collection ,
238
239
filter : Document ,
@@ -252,13 +253,25 @@ export class FindOneAndReplaceOperation extends FindAndModifyOperation {
252
253
}
253
254
254
255
super ( collection , filter , options ) ;
255
- this . cmdBase . update = replacement ;
256
- configureFindAndModifyCmdBaseUpdateOpts ( this . cmdBase , options ) ;
256
+ this . replacement = replacement ;
257
+ }
258
+
259
+ override buildCommandDocument (
260
+ connection : Connection ,
261
+ session ?: ClientSession
262
+ ) : Document & FindAndModifyCmdBase {
263
+ const document = super . buildCommandDocument ( connection , session ) ;
264
+ document . update = this . replacement ;
265
+ configureFindAndModifyCmdBaseUpdateOpts ( document , this . options ) ;
266
+ return document ;
257
267
}
258
268
}
259
269
260
270
/** @internal */
261
271
export class FindOneAndUpdateOperation extends FindAndModifyOperation {
272
+ override options : FindOneAndUpdateOptions ;
273
+
274
+ private update : Document ;
262
275
constructor (
263
276
collection : Collection ,
264
277
filter : Document ,
@@ -278,12 +291,23 @@ export class FindOneAndUpdateOperation extends FindAndModifyOperation {
278
291
}
279
292
280
293
super ( collection , filter , options ) ;
281
- this . cmdBase . update = update ;
282
- configureFindAndModifyCmdBaseUpdateOpts ( this . cmdBase , options ) ;
294
+ this . update = update ;
295
+ this . options = options ;
296
+ }
283
297
284
- if ( options . arrayFilters ) {
285
- this . cmdBase . arrayFilters = options . arrayFilters ;
298
+ override buildCommandDocument (
299
+ connection : Connection ,
300
+ session ?: ClientSession
301
+ ) : Document & FindAndModifyCmdBase {
302
+ const document = super . buildCommandDocument ( connection , session ) ;
303
+ document . update = this . update ;
304
+ configureFindAndModifyCmdBaseUpdateOpts ( document , this . options ) ;
305
+
306
+ if ( this . options . arrayFilters ) {
307
+ document . arrayFilters = this . options . arrayFilters ;
286
308
}
309
+
310
+ return document ;
287
311
}
288
312
}
289
313
0 commit comments