Skip to content

Commit 8758890

Browse files
authoredSep 15, 2022
feat(NODE-4634): add support for bulk FindOperators.hint() (#3408)
1 parent d29b3d9 commit 8758890

File tree

3 files changed

+77
-4
lines changed

3 files changed

+77
-4
lines changed
 

‎src/bulk/common.ts

+12-2
Original file line numberDiff line numberDiff line change
@@ -784,7 +784,7 @@ export class FindOperators {
784784
}
785785

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

798798
/** Add a single update operation to the bulk operation */
799-
updateOne(updateDocument: Document): BulkOperationBase {
799+
updateOne(updateDocument: Document | Document[]): BulkOperationBase {
800800
if (!hasAtomicOperators(updateDocument)) {
801801
throw new MongoInvalidArgumentError('Update document requires atomic operators');
802802
}
@@ -868,6 +868,16 @@ export class FindOperators {
868868
this.bulkOperation.s.currentOp.arrayFilters = arrayFilters;
869869
return this;
870870
}
871+
872+
/** Specifies hint for the bulk operation. */
873+
hint(hint: Hint): this {
874+
if (!this.bulkOperation.s.currentOp) {
875+
this.bulkOperation.s.currentOp = {};
876+
}
877+
878+
this.bulkOperation.s.currentOp.hint = hint;
879+
return this;
880+
}
871881
}
872882

873883
/** @internal */

‎src/operations/update.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export interface UpdateOptions extends CommandOperationOptions {
2222
/** Specifies a collation */
2323
collation?: CollationOptions;
2424
/** Specify that the update query should only consider plans using the hinted index */
25-
hint?: string | Document;
25+
hint?: Hint;
2626
/** When true, creates a new document if no document matches the query */
2727
upsert?: boolean;
2828
/** Map of parameter names and values that can be accessed using $$var (requires MongoDB 5.0). */
@@ -280,7 +280,7 @@ export class ReplaceOneOperation extends UpdateOperation {
280280

281281
export function makeUpdateStatement(
282282
filter: Document,
283-
update: Document,
283+
update: Document | Document[],
284284
options: UpdateOptions & { multi?: boolean }
285285
): UpdateStatement {
286286
if (filter == null || typeof filter !== 'object') {

‎test/integration/crud/bulk.test.ts

+63
Original file line numberDiff line numberDiff line change
@@ -1688,6 +1688,51 @@ describe('Bulk', function () {
16881688
}
16891689
});
16901690

1691+
it('should apply hint via FindOperators', {
1692+
metadata: { requires: { mongodb: '>= 4.4' } },
1693+
async test() {
1694+
const bulk = client.db().collection('coll').initializeOrderedBulkOp();
1695+
1696+
const events = [];
1697+
client.on('commandStarted', event => {
1698+
if (['update', 'delete'].includes(event.commandName)) {
1699+
events.push(event);
1700+
}
1701+
});
1702+
1703+
// updates
1704+
bulk
1705+
.find({ b: 1 })
1706+
.hint({ b: 1 })
1707+
.updateOne({ $set: { b: 2 } });
1708+
bulk
1709+
.find({ b: 2 })
1710+
.hint({ b: 1 })
1711+
.update({ $set: { b: 3 } });
1712+
bulk.find({ b: 3 }).hint({ b: 1 }).replaceOne({ b: 2 });
1713+
1714+
// deletes
1715+
bulk.find({ b: 2 }).hint({ b: 1 }).deleteOne();
1716+
bulk.find({ b: 1 }).hint({ b: 1 }).delete();
1717+
1718+
await bulk.execute();
1719+
1720+
expect(events).to.be.an('array').with.length.at.least(1);
1721+
expect(events[0]).property('commandName').to.equal('update');
1722+
const updateCommand = events[0].command;
1723+
expect(updateCommand).property('updates').to.be.an('array').with.length(3);
1724+
updateCommand.updates.forEach(statement => {
1725+
expect(statement).property('hint').to.eql({ b: 1 });
1726+
});
1727+
expect(events[1]).property('commandName').to.equal('delete');
1728+
const deleteCommand = events[1].command;
1729+
expect(deleteCommand).property('deletes').to.be.an('array').with.length(2);
1730+
deleteCommand.deletes.forEach(statement => {
1731+
expect(statement).property('hint').to.eql({ b: 1 });
1732+
});
1733+
}
1734+
});
1735+
16911736
it('should apply arrayFilters to bulk updates via FindOperators', {
16921737
metadata: { requires: { mongodb: '>= 3.6' } },
16931738
test: function (done) {
@@ -1737,6 +1782,24 @@ describe('Bulk', function () {
17371782
}
17381783
});
17391784

1785+
it('should accept pipeline-style updates', {
1786+
metadata: { requires: { mongodb: '>= 4.2' } },
1787+
async test() {
1788+
const coll = client.db().collection('coll');
1789+
const bulk = coll.initializeOrderedBulkOp();
1790+
1791+
coll.insertMany([{ a: 1 }, { a: 2 }]);
1792+
1793+
bulk.find({ a: 1 }).updateOne([{ $project: { a: { $add: ['$a', 10] } } }]);
1794+
bulk.find({ a: 2 }).update([{ $project: { a: { $add: ['$a', 100] } } }]);
1795+
1796+
await bulk.execute();
1797+
1798+
const contents = await coll.find().project({ _id: 0 }).toArray();
1799+
expect(contents).to.deep.equal([{ a: 11 }, { a: 102 }]);
1800+
}
1801+
});
1802+
17401803
it('should throw an error if raw operations are passed to bulkWrite', function () {
17411804
const coll = client.db().collection('single_bulk_write_error');
17421805
return coll

0 commit comments

Comments
 (0)
Please sign in to comment.