Skip to content

Commit 3bf0025

Browse files
authored
fix(shell-api): map fields to projection in findAndModify MONGOSH-1820 (#2100)
1 parent 1570f12 commit 3bf0025

File tree

4 files changed

+32
-1
lines changed

4 files changed

+32
-1
lines changed

packages/shell-api/src/collection.spec.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1798,11 +1798,12 @@ describe('Collection', function () {
17981798
...options,
17991799
});
18001800

1801+
const { fields: projection, ...expectedOptions } = options;
18011802
expect(serviceProvider.findOneAndDelete).to.have.been.calledWith(
18021803
collection._database._name,
18031804
collection._name,
18041805
{ query: 1 },
1805-
{ ...options, sort: { sort: 1 } }
1806+
{ ...expectedOptions, sort: { sort: 1 }, projection }
18061807
);
18071808
});
18081809
});

packages/shell-api/src/collection.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,8 +482,19 @@ export default class Collection extends ShellApiWithMongoClass {
482482
FindAndModifyMethodShellOptions,
483483
'query' | 'update'
484484
> = { ...options };
485+
if (
486+
reducedOptions.projection !== undefined &&
487+
reducedOptions.fields !== undefined
488+
) {
489+
throw new MongoshInvalidInputError(
490+
'Cannot specify both .fields and .projection for findAndModify()',
491+
CommonErrors.InvalidArgument
492+
);
493+
}
494+
reducedOptions.projection ??= reducedOptions.fields;
485495
delete (reducedOptions as any).query;
486496
delete (reducedOptions as any).update;
497+
delete (reducedOptions as any).fields;
487498
if (options.remove) {
488499
return this.findOneAndDelete(options.query, reducedOptions);
489500
}

packages/shell-api/src/helpers.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -783,6 +783,7 @@ export type FindAndModifyMethodShellOptions = {
783783
remove?: boolean;
784784
new?: boolean;
785785
fields?: Document;
786+
projection?: Document;
786787
upsert?: boolean;
787788
bypassDocumentValidation?: boolean;
788789
writeConcern?: Document;

packages/shell-api/src/integration.spec.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1097,6 +1097,24 @@ describe('Shell API (integration)', function () {
10971097
});
10981098
});
10991099

1100+
it('projects according to `fields`', async function () {
1101+
const result = await collection.findAndModify({
1102+
query: { doc: 4 },
1103+
new: true,
1104+
update: { doc: 4, asdf: true },
1105+
upsert: true,
1106+
fields: { asdf: 1, _id: 1 },
1107+
});
1108+
expect(Object.keys(result!)).to.deep.equal(['_id', 'asdf']);
1109+
expect(result!._id.constructor.name).to.equal('ObjectId');
1110+
expect(result!.asdf).to.equal(true);
1111+
1112+
expect(await findAllWithoutId(dbName, collectionName)).to.deep.include({
1113+
doc: 4,
1114+
asdf: true,
1115+
});
1116+
});
1117+
11001118
context('on server 4.2+', function () {
11011119
skipIfServerVersion(testServer, '< 4.2');
11021120
it('allows update pipelines', async function () {

0 commit comments

Comments
 (0)