diff --git a/src/bulk/unordered.ts b/src/bulk/unordered.ts index c718377722..77c4f33082 100644 --- a/src/bulk/unordered.ts +++ b/src/bulk/unordered.ts @@ -112,7 +112,7 @@ export class UnorderedBulkOperation extends BulkOperationBase { if (batchType === BatchType.INSERT) { this.s.currentInsertBatch = this.s.currentBatch; this.s.bulkResult.insertedIds.push({ - index: this.s.bulkResult.insertedIds.length, + index: this.s.currentIndex - 1, _id: (document as Document)._id }); } else if (batchType === BatchType.UPDATE) { diff --git a/test/integration/crud/bulk.test.ts b/test/integration/crud/bulk.test.ts index 5390babe16..f48ae9e3cb 100644 --- a/test/integration/crud/bulk.test.ts +++ b/test/integration/crud/bulk.test.ts @@ -338,6 +338,23 @@ describe('Bulk', function () { { 0: 0, 3: 3 } ); }); + + it('contains the correct insertedIds when inserts are mixed with other operations', async function () { + // The inserts sit at operation indexes 0, 2 and 4, so the count of inserts seen + // differs from the originating operation index. The update and delete match nothing; + // they are only here to move the inserts off the positions a running count produces. + await assertFailsWithDuplicateFields( + [ + { insertOne: { _id: 0, a: 1 } }, + { updateOne: { filter: { nothing: 1 }, update: { $set: { b: 1 } } } }, + { insertOne: { _id: 2, a: 1 } }, + { deleteOne: { filter: { nothing: 1 } } }, + { insertOne: { _id: 4, a: 2 } } + ], + false, + { 0: 0, 4: 4 } + ); + }); }); }); }); diff --git a/test/unit/bulk.test.ts b/test/unit/bulk.test.ts new file mode 100644 index 0000000000..88d4482659 --- /dev/null +++ b/test/unit/bulk.test.ts @@ -0,0 +1,63 @@ +import { expect } from 'chai'; + +import { + DEFAULT_PK_FACTORY, + MongoDBCollectionNamespace, + OrderedBulkOperation, + UnorderedBulkOperation +} from '../mongodb'; + +describe('Bulk Operation insertedIds', function () { + function makeFakeCollection() { + const topology = { + lastHello() { + return { maxBsonObjectSize: 16 * 1024 * 1024, maxWriteBatchSize: 1000 }; + }, + s: { options: {} } + }; + const collection: any = { + client: { topology }, + topology, + db: { options: {} }, + bsonOptions: {}, + s: { + namespace: new MongoDBCollectionNamespace('test', 'coll'), + pkFactory: DEFAULT_PK_FACTORY, + bsonOptions: {}, + collection: undefined + } + }; + collection.s.collection = collection; + return collection; + } + + function addMixedOperations(bulk: OrderedBulkOperation | UnorderedBulkOperation) { + bulk.raw({ insertOne: { document: { _id: 'a', x: 1 } } }); + bulk.raw({ updateOne: { filter: { x: 1 }, update: { $set: { y: 2 } } } }); + bulk.raw({ insertOne: { document: { _id: 'b', x: 3 } } }); + bulk.raw({ deleteOne: { filter: { x: 3 } } }); + bulk.raw({ insertOne: { document: { _id: 'c', x: 5 } } }); + } + + it('ordered bulk keys insertedIds by the originating operation index', function () { + const bulk = new OrderedBulkOperation(makeFakeCollection(), { ordered: true } as any); + addMixedOperations(bulk); + const insertedIds = (bulk as any).s.bulkResult.insertedIds; + expect(insertedIds).to.deep.equal([ + { index: 0, _id: 'a' }, + { index: 2, _id: 'b' }, + { index: 4, _id: 'c' } + ]); + }); + + it('unordered bulk keys insertedIds by the originating operation index', function () { + const bulk = new UnorderedBulkOperation(makeFakeCollection(), { ordered: false } as any); + addMixedOperations(bulk); + const insertedIds = (bulk as any).s.bulkResult.insertedIds; + expect(insertedIds).to.deep.equal([ + { index: 0, _id: 'a' }, + { index: 2, _id: 'b' }, + { index: 4, _id: 'c' } + ]); + }); +});