Skip to content

Commit f4085ac

Browse files
committed
feat(NODE-3765): make _id optional in replacement for replaceOne operations
The _id field is immutable in a replaceOne operation, so it does not make sense to require passing it. Also, this makes replaceOne consistent with insertOne.
1 parent 52520aa commit f4085ac

File tree

4 files changed

+49
-6
lines changed

4 files changed

+49
-6
lines changed

src/bulk/common.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ export interface ReplaceOneModel<TSchema extends Document = Document> {
7979
/** The filter to limit the replaced document. */
8080
filter: Filter<TSchema>;
8181
/** The document with which to replace the matched document. */
82-
replacement: TSchema;
82+
replacement: OptionalId<TSchema>;
8383
/** Specifies a collation. */
8484
collation?: CollationOptions;
8585
/** The index to use. If specified, then the query system will only consider plans using the hinted index. */

src/collection.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -459,26 +459,29 @@ export class Collection<TSchema extends Document = Document> {
459459
* @param options - Optional settings for the command
460460
* @param callback - An optional callback, a Promise will be returned if none is provided
461461
*/
462-
replaceOne(filter: Filter<TSchema>, replacement: TSchema): Promise<UpdateResult | Document>;
463462
replaceOne(
464463
filter: Filter<TSchema>,
465-
replacement: TSchema,
464+
replacement: OptionalId<TSchema>
465+
): Promise<UpdateResult | Document>;
466+
replaceOne(
467+
filter: Filter<TSchema>,
468+
replacement: OptionalId<TSchema>,
466469
callback: Callback<UpdateResult | Document>
467470
): void;
468471
replaceOne(
469472
filter: Filter<TSchema>,
470-
replacement: TSchema,
473+
replacement: OptionalId<TSchema>,
471474
options: ReplaceOptions
472475
): Promise<UpdateResult | Document>;
473476
replaceOne(
474477
filter: Filter<TSchema>,
475-
replacement: TSchema,
478+
replacement: OptionalId<TSchema>,
476479
options: ReplaceOptions,
477480
callback: Callback<UpdateResult | Document>
478481
): void;
479482
replaceOne(
480483
filter: Filter<TSchema>,
481-
replacement: TSchema,
484+
replacement: OptionalId<TSchema>,
482485
options?: ReplaceOptions | Callback<UpdateResult | Document>,
483486
callback?: Callback<UpdateResult | Document>
484487
): Promise<UpdateResult | Document> | void {

test/types/community/collection/bulkWrite.test-d.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,24 @@ collectionType.bulkWrite([
181181
}
182182
}
183183
]);
184+
// allow a replacement doc without an _id
185+
collectionType.bulkWrite([
186+
{
187+
replaceOne: {
188+
filter: {},
189+
replacement: {
190+
dateField: new Date(),
191+
fruitTags: [],
192+
numberField: 0,
193+
readonlyFruitTags: [],
194+
stringField: 'string',
195+
subInterfaceArray: [],
196+
subInterfaceField: { field1: '1', field2: '2' }
197+
},
198+
upsert: true
199+
}
200+
}
201+
]);
184202

185203
expectError(
186204
collectionType.bulkWrite([
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { expectError } from 'tsd';
2+
import { MongoClient, ObjectId } from '../../../../src';
3+
4+
// test collection.replaceX functions
5+
const client = new MongoClient('');
6+
const db = client.db('test');
7+
8+
interface TestModel {
9+
_id: ObjectId;
10+
stringField: string;
11+
}
12+
13+
const collection = db.collection<TestModel>('testCollection');
14+
15+
// should accept a replacement doc with an _id
16+
await collection.replaceOne({}, { _id: new ObjectId(), stringField: 'a' });
17+
18+
// should accept a replacement doc without an _id
19+
await collection.replaceOne({}, { stringField: 'b' });
20+
21+
// should not allow _id with a non-ObjectId type
22+
expectError(await collection.replaceOne({}, { _id: 1, stringField: 'c' }));

0 commit comments

Comments
 (0)