Skip to content

Commit 53792ae

Browse files
findAndModify
1 parent 42eb9d8 commit 53792ae

File tree

1 file changed

+85
-58
lines changed

1 file changed

+85
-58
lines changed

src/operations/find_and_modify.ts

Lines changed: 85 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1+
import { type Connection } from '..';
12
import type { Document } from '../bson';
3+
import { MongoDBResponse } from '../cmap/wire_protocol/responses';
24
import type { Collection } from '../collection';
35
import { MongoCompatibilityError, MongoInvalidArgumentError } from '../error';
46
import { ReadPreference } from '../read_preference';
5-
import type { Server } from '../sdam/server';
67
import type { ClientSession } from '../sessions';
78
import { formatSort, type Sort, type SortForCmd } from '../sort';
8-
import { type TimeoutContext } from '../timeout';
9-
import { decorateWithCollation, hasAtomicOperators, maxWireVersion } from '../utils';
9+
import { hasAtomicOperators, maxWireVersion } from '../utils';
1010
import { type WriteConcern, type WriteConcernSettings } from '../write_concern';
11-
import { CommandOperation, type CommandOperationOptions } from './command';
11+
import { type CommandOperationOptions, ModernizedCommandOperation } from './command';
1212
import { Aspect, defineAspects } from './operation';
1313

1414
/** @public */
@@ -120,12 +120,12 @@ function configureFindAndModifyCmdBaseUpdateOpts(
120120
}
121121

122122
/** @internal */
123-
export class FindAndModifyOperation extends CommandOperation<Document> {
123+
export class FindAndModifyOperation extends ModernizedCommandOperation<Document> {
124+
override SERVER_COMMAND_RESPONSE_TYPE = MongoDBResponse;
125+
124126
override options: FindOneAndReplaceOptions | FindOneAndUpdateOptions | FindOneAndDeleteOptions;
125-
cmdBase: FindAndModifyCmdBase;
126127
collection: Collection;
127128
query: Document;
128-
doc?: Document;
129129

130130
constructor(
131131
collection: Collection,
@@ -134,87 +134,84 @@ export class FindAndModifyOperation extends CommandOperation<Document> {
134134
) {
135135
super(collection, options);
136136
this.options = options ?? {};
137-
this.cmdBase = {
137+
138+
options.includeResultMetadata ??= false;
139+
140+
// force primary read preference
141+
this.readPreference = ReadPreference.primary;
142+
143+
this.collection = collection;
144+
this.query = query;
145+
}
146+
147+
override get commandName() {
148+
return 'findAndModify' as const;
149+
}
150+
151+
override buildCommandDocument(
152+
connection: Connection,
153+
_session?: ClientSession
154+
): FindAndModifyCmdBase {
155+
const coll = this.collection;
156+
const query = this.query;
157+
const options = this.options;
158+
159+
// Create findAndModify command object
160+
const command: FindAndModifyCmdBase & Document = {
161+
findAndModify: coll.collectionName,
162+
query: query,
138163
remove: false,
139164
new: false,
140165
upsert: false
141166
};
142167

143-
options.includeResultMetadata ??= false;
144-
145168
const sort = formatSort(options.sort);
146169
if (sort) {
147-
this.cmdBase.sort = sort;
170+
command.sort = sort;
148171
}
149172

150173
if (options.projection) {
151-
this.cmdBase.fields = options.projection;
174+
command.fields = options.projection;
152175
}
153176

154177
if (options.maxTimeMS) {
155-
this.cmdBase.maxTimeMS = options.maxTimeMS;
178+
command.maxTimeMS = options.maxTimeMS;
156179
}
157180

158181
// Decorate the findAndModify command with the write Concern
159182
if (options.writeConcern) {
160-
this.cmdBase.writeConcern = options.writeConcern;
183+
command.writeConcern = options.writeConcern;
161184
}
162185

163186
if (options.let) {
164-
this.cmdBase.let = options.let;
187+
command.let = options.let;
165188
}
166189

167190
// we check for undefined specifically here to allow falsy values
168191
// eslint-disable-next-line no-restricted-syntax
169192
if (options.comment !== undefined) {
170-
this.cmdBase.comment = options.comment;
193+
command.comment = options.comment;
171194
}
172195

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);
201-
202196
if (options.hint) {
203197
// TODO: once this method becomes a CommandOperation we will have the server
204198
// in place to check.
205199
const unacknowledgedWrite = this.writeConcern?.w === 0;
206-
if (unacknowledgedWrite || maxWireVersion(server) < 8) {
200+
if (unacknowledgedWrite || maxWireVersion(connection) < 8) {
207201
throw new MongoCompatibilityError(
208202
'The current topology does not support a hint on findAndModify commands'
209203
);
210204
}
211205

212-
cmd.hint = options.hint;
206+
command.hint = options.hint;
213207
}
214208

215-
// Execute the command
216-
const result = await super.executeCommand(server, session, cmd, timeoutContext);
217-
return options.includeResultMetadata ? result : (result.value ?? null);
209+
return command;
210+
}
211+
212+
override handleOk(response: InstanceType<typeof this.SERVER_COMMAND_RESPONSE_TYPE>): Document {
213+
const result = super.handleOk(response);
214+
return this.options.includeResultMetadata ? result : (result.value ?? null);
218215
}
219216
}
220217

@@ -227,12 +224,21 @@ export class FindOneAndDeleteOperation extends FindAndModifyOperation {
227224
}
228225

229226
super(collection, filter, options);
230-
this.cmdBase.remove = true;
227+
}
228+
229+
override buildCommandDocument(
230+
connection: Connection,
231+
session?: ClientSession
232+
): FindAndModifyCmdBase {
233+
const command = super.buildCommandDocument(connection, session);
234+
command.remove = true;
235+
return command;
231236
}
232237
}
233238

234239
/** @internal */
235240
export class FindOneAndReplaceOperation extends FindAndModifyOperation {
241+
private replacement: Document;
236242
constructor(
237243
collection: Collection,
238244
filter: Document,
@@ -250,15 +256,27 @@ export class FindOneAndReplaceOperation extends FindAndModifyOperation {
250256
if (hasAtomicOperators(replacement)) {
251257
throw new MongoInvalidArgumentError('Replacement document must not contain atomic operators');
252258
}
253-
254259
super(collection, filter, options);
255-
this.cmdBase.update = replacement;
256-
configureFindAndModifyCmdBaseUpdateOpts(this.cmdBase, options);
260+
261+
this.replacement = replacement;
262+
}
263+
264+
override buildCommandDocument(
265+
connection: Connection,
266+
session?: ClientSession
267+
): FindAndModifyCmdBase {
268+
const command = super.buildCommandDocument(connection, session);
269+
command.update = this.replacement;
270+
configureFindAndModifyCmdBaseUpdateOpts(command, this.options);
271+
return command;
257272
}
258273
}
259274

260275
/** @internal */
261276
export class FindOneAndUpdateOperation extends FindAndModifyOperation {
277+
private update: Document;
278+
override options: FindOneAndUpdateOptions;
279+
262280
constructor(
263281
collection: Collection,
264282
filter: Document,
@@ -278,12 +296,21 @@ export class FindOneAndUpdateOperation extends FindAndModifyOperation {
278296
}
279297

280298
super(collection, filter, options);
281-
this.cmdBase.update = update;
282-
configureFindAndModifyCmdBaseUpdateOpts(this.cmdBase, options);
299+
this.update = update;
300+
this.options = options;
301+
}
283302

284-
if (options.arrayFilters) {
285-
this.cmdBase.arrayFilters = options.arrayFilters;
303+
override buildCommandDocument(
304+
connection: Connection,
305+
session?: ClientSession
306+
): FindAndModifyCmdBase {
307+
const command = super.buildCommandDocument(connection, session);
308+
command.update = this.update;
309+
configureFindAndModifyCmdBaseUpdateOpts(command, this.options);
310+
if (this.options.arrayFilters) {
311+
command.arrayFilters = this.options.arrayFilters;
286312
}
313+
return command;
287314
}
288315
}
289316

0 commit comments

Comments
 (0)