Skip to content

Commit 90d11e8

Browse files
find and modify
1 parent 580a491 commit 90d11e8

File tree

1 file changed

+80
-56
lines changed

1 file changed

+80
-56
lines changed

src/operations/find_and_modify.ts

Lines changed: 80 additions & 56 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 { decorateWithCollation, hasAtomicOperators } 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,9 +120,9 @@ 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;
124125
override options: FindOneAndReplaceOptions | FindOneAndUpdateOptions | FindOneAndDeleteOptions;
125-
cmdBase: FindAndModifyCmdBase;
126126
collection: Collection;
127127
query: Document;
128128
doc?: Document;
@@ -133,8 +133,26 @@ export class FindAndModifyOperation extends CommandOperation<Document> {
133133
options: FindOneAndReplaceOptions | FindOneAndUpdateOptions | FindOneAndDeleteOptions
134134
) {
135135
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,
138156
remove: false,
139157
new: false,
140158
upsert: false
@@ -144,77 +162,51 @@ export class FindAndModifyOperation extends CommandOperation<Document> {
144162

145163
const sort = formatSort(options.sort);
146164
if (sort) {
147-
this.cmdBase.sort = sort;
165+
command.sort = sort;
148166
}
149167

150168
if (options.projection) {
151-
this.cmdBase.fields = options.projection;
169+
command.fields = options.projection;
152170
}
153171

154172
if (options.maxTimeMS) {
155-
this.cmdBase.maxTimeMS = options.maxTimeMS;
173+
command.maxTimeMS = options.maxTimeMS;
156174
}
157175

158176
// Decorate the findAndModify command with the write Concern
159177
if (options.writeConcern) {
160-
this.cmdBase.writeConcern = options.writeConcern;
178+
command.writeConcern = options.writeConcern;
161179
}
162180

163181
if (options.let) {
164-
this.cmdBase.let = options.let;
182+
command.let = options.let;
165183
}
166184

167185
// we check for undefined specifically here to allow falsy values
168186
// eslint-disable-next-line no-restricted-syntax
169187
if (options.comment !== undefined) {
170-
this.cmdBase.comment = options.comment;
188+
command.comment = options.comment;
171189
}
172190

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);
201192

202193
if (options.hint) {
203-
// TODO: once this method becomes a CommandOperation we will have the server
204-
// in place to check.
205194
const unacknowledgedWrite = this.writeConcern?.w === 0;
206-
if (unacknowledgedWrite || maxWireVersion(server) < 8) {
195+
if (unacknowledgedWrite) {
207196
throw new MongoCompatibilityError(
208197
'The current topology does not support a hint on findAndModify commands'
209198
);
210199
}
211200

212-
cmd.hint = options.hint;
201+
command.hint = options.hint;
213202
}
214203

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);
218210
}
219211
}
220212

@@ -227,12 +219,21 @@ export class FindOneAndDeleteOperation extends FindAndModifyOperation {
227219
}
228220

229221
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;
231231
}
232232
}
233233

234234
/** @internal */
235235
export class FindOneAndReplaceOperation extends FindAndModifyOperation {
236+
private replacement: Document;
236237
constructor(
237238
collection: Collection,
238239
filter: Document,
@@ -252,13 +253,25 @@ export class FindOneAndReplaceOperation extends FindAndModifyOperation {
252253
}
253254

254255
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;
257267
}
258268
}
259269

260270
/** @internal */
261271
export class FindOneAndUpdateOperation extends FindAndModifyOperation {
272+
override options: FindOneAndUpdateOptions;
273+
274+
private update: Document;
262275
constructor(
263276
collection: Collection,
264277
filter: Document,
@@ -278,12 +291,23 @@ export class FindOneAndUpdateOperation extends FindAndModifyOperation {
278291
}
279292

280293
super(collection, filter, options);
281-
this.cmdBase.update = update;
282-
configureFindAndModifyCmdBaseUpdateOpts(this.cmdBase, options);
294+
this.update = update;
295+
this.options = options;
296+
}
283297

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;
286308
}
309+
310+
return document;
287311
}
288312
}
289313

0 commit comments

Comments
 (0)