Skip to content

Commit

Permalink
feat(NODE-4634): add support for bulk FindOperators.hint() (#3408)
Browse files Browse the repository at this point in the history
  • Loading branch information
addaleax committed Sep 15, 2022
1 parent d29b3d9 commit 8758890
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 4 deletions.
14 changes: 12 additions & 2 deletions src/bulk/common.ts
Expand Up @@ -784,7 +784,7 @@ export class FindOperators {
}

/** Add a multiple update operation to the bulk operation */
update(updateDocument: Document): BulkOperationBase {
update(updateDocument: Document | Document[]): BulkOperationBase {
const currentOp = buildCurrentOp(this.bulkOperation);
return this.bulkOperation.addToOperationsList(
BatchType.UPDATE,
Expand All @@ -796,7 +796,7 @@ export class FindOperators {
}

/** Add a single update operation to the bulk operation */
updateOne(updateDocument: Document): BulkOperationBase {
updateOne(updateDocument: Document | Document[]): BulkOperationBase {
if (!hasAtomicOperators(updateDocument)) {
throw new MongoInvalidArgumentError('Update document requires atomic operators');
}
Expand Down Expand Up @@ -868,6 +868,16 @@ export class FindOperators {
this.bulkOperation.s.currentOp.arrayFilters = arrayFilters;
return this;
}

/** Specifies hint for the bulk operation. */
hint(hint: Hint): this {
if (!this.bulkOperation.s.currentOp) {
this.bulkOperation.s.currentOp = {};
}

this.bulkOperation.s.currentOp.hint = hint;
return this;
}
}

/** @internal */
Expand Down
4 changes: 2 additions & 2 deletions src/operations/update.ts
Expand Up @@ -22,7 +22,7 @@ export interface UpdateOptions extends CommandOperationOptions {
/** Specifies a collation */
collation?: CollationOptions;
/** Specify that the update query should only consider plans using the hinted index */
hint?: string | Document;
hint?: Hint;
/** When true, creates a new document if no document matches the query */
upsert?: boolean;
/** Map of parameter names and values that can be accessed using $$var (requires MongoDB 5.0). */
Expand Down Expand Up @@ -280,7 +280,7 @@ export class ReplaceOneOperation extends UpdateOperation {

export function makeUpdateStatement(
filter: Document,
update: Document,
update: Document | Document[],
options: UpdateOptions & { multi?: boolean }
): UpdateStatement {
if (filter == null || typeof filter !== 'object') {
Expand Down
63 changes: 63 additions & 0 deletions test/integration/crud/bulk.test.ts
Expand Up @@ -1688,6 +1688,51 @@ describe('Bulk', function () {
}
});

it('should apply hint via FindOperators', {
metadata: { requires: { mongodb: '>= 4.4' } },
async test() {
const bulk = client.db().collection('coll').initializeOrderedBulkOp();

const events = [];
client.on('commandStarted', event => {
if (['update', 'delete'].includes(event.commandName)) {
events.push(event);
}
});

// updates
bulk
.find({ b: 1 })
.hint({ b: 1 })
.updateOne({ $set: { b: 2 } });
bulk
.find({ b: 2 })
.hint({ b: 1 })
.update({ $set: { b: 3 } });
bulk.find({ b: 3 }).hint({ b: 1 }).replaceOne({ b: 2 });

// deletes
bulk.find({ b: 2 }).hint({ b: 1 }).deleteOne();
bulk.find({ b: 1 }).hint({ b: 1 }).delete();

await bulk.execute();

expect(events).to.be.an('array').with.length.at.least(1);
expect(events[0]).property('commandName').to.equal('update');
const updateCommand = events[0].command;
expect(updateCommand).property('updates').to.be.an('array').with.length(3);
updateCommand.updates.forEach(statement => {
expect(statement).property('hint').to.eql({ b: 1 });
});
expect(events[1]).property('commandName').to.equal('delete');
const deleteCommand = events[1].command;
expect(deleteCommand).property('deletes').to.be.an('array').with.length(2);
deleteCommand.deletes.forEach(statement => {
expect(statement).property('hint').to.eql({ b: 1 });
});
}
});

it('should apply arrayFilters to bulk updates via FindOperators', {
metadata: { requires: { mongodb: '>= 3.6' } },
test: function (done) {
Expand Down Expand Up @@ -1737,6 +1782,24 @@ describe('Bulk', function () {
}
});

it('should accept pipeline-style updates', {
metadata: { requires: { mongodb: '>= 4.2' } },
async test() {
const coll = client.db().collection('coll');
const bulk = coll.initializeOrderedBulkOp();

coll.insertMany([{ a: 1 }, { a: 2 }]);

bulk.find({ a: 1 }).updateOne([{ $project: { a: { $add: ['$a', 10] } } }]);
bulk.find({ a: 2 }).update([{ $project: { a: { $add: ['$a', 100] } } }]);

await bulk.execute();

const contents = await coll.find().project({ _id: 0 }).toArray();
expect(contents).to.deep.equal([{ a: 11 }, { a: 102 }]);
}
});

it('should throw an error if raw operations are passed to bulkWrite', function () {
const coll = client.db().collection('single_bulk_write_error');
return coll
Expand Down

0 comments on commit 8758890

Please sign in to comment.