Skip to content

Commit ddb8d90

Browse files
committed
fix(aggregate): do not send batchSize for aggregation with $out
Sending a batchSize of 0 will break the cursor, and in general we should not be sending batchSize for aggregation pipelines that contain a $out stage. Fixes NODE-1850
1 parent f73bd06 commit ddb8d90

File tree

2 files changed

+72
-5
lines changed

2 files changed

+72
-5
lines changed

lib/operations/aggregate.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ function aggregate(db, coll, pipeline, options, callback) {
2525
const isDbAggregate = typeof coll === 'string';
2626
const target = isDbAggregate ? db : coll;
2727
const topology = target.s.topology;
28-
let ignoreReadConcern = false;
28+
let hasOutStage = false;
2929

3030
if (typeof options.out === 'string') {
3131
pipeline = pipeline.concat({ $out: options.out });
32-
ignoreReadConcern = true;
32+
hasOutStage = true;
3333
} else if (pipeline.length > 0 && pipeline[pipeline.length - 1]['$out']) {
34-
ignoreReadConcern = true;
34+
hasOutStage = true;
3535
}
3636

3737
let command;
@@ -52,7 +52,7 @@ function aggregate(db, coll, pipeline, options, callback) {
5252

5353
const takesWriteConcern = topology.capabilities().commandsTakeWriteConcern;
5454

55-
if (!ignoreReadConcern) {
55+
if (!hasOutStage) {
5656
decorateWithReadConcern(command, target, options);
5757
}
5858

@@ -96,7 +96,7 @@ function aggregate(db, coll, pipeline, options, callback) {
9696
}
9797

9898
options.cursor = options.cursor || {};
99-
if (options.batchSize) options.cursor.batchSize = options.batchSize;
99+
if (options.batchSize && !hasOutStage) options.cursor.batchSize = options.batchSize;
100100
command.cursor = options.cursor;
101101

102102
// promiseLibrary

test/functional/aggregation_tests.js

+67
Original file line numberDiff line numberDiff line change
@@ -1354,4 +1354,71 @@ describe('Aggregation', function() {
13541354
// DOC_END
13551355
}
13561356
});
1357+
1358+
it('should not send a batchSize for aggregations with an out stage', {
1359+
metadata: { requires: { topology: ['single', 'replicaset'] } },
1360+
test: function(done) {
1361+
const databaseName = this.configuration.db;
1362+
const client = this.configuration.newClient(this.configuration.writeConcernMax(), {
1363+
poolSize: 1,
1364+
monitorCommands: true
1365+
});
1366+
1367+
let err;
1368+
let coll1;
1369+
let coll2;
1370+
const events = [];
1371+
1372+
client.on('commandStarted', e => {
1373+
if (e.commandName === 'aggregate') {
1374+
events.push(e);
1375+
}
1376+
});
1377+
1378+
client
1379+
.connect()
1380+
.then(() => {
1381+
coll1 = client.db(databaseName).collection('coll1');
1382+
coll2 = client.db(databaseName).collection('coll2');
1383+
1384+
return Promise.all([coll1.remove({}), coll2.remove({})]);
1385+
})
1386+
.then(() => {
1387+
const docs = Array.from({ length: 10 }).map(() => ({ a: 1 }));
1388+
1389+
return coll1.insertMany(docs);
1390+
})
1391+
.then(() => {
1392+
return Promise.all(
1393+
[
1394+
coll1.aggregate([{ $out: 'coll2' }]),
1395+
coll1.aggregate([{ $out: 'coll2' }], { batchSize: 0 }),
1396+
coll1.aggregate([{ $out: 'coll2' }], { batchSize: 1 }),
1397+
coll1.aggregate([{ $out: 'coll2' }], { batchSize: 30 }),
1398+
coll1.aggregate([{ $match: { a: 1 } }, { $out: 'coll2' }]),
1399+
coll1.aggregate([{ $match: { a: 1 } }, { $out: 'coll2' }], { batchSize: 0 }),
1400+
coll1.aggregate([{ $match: { a: 1 } }, { $out: 'coll2' }], { batchSize: 1 }),
1401+
coll1.aggregate([{ $match: { a: 1 } }, { $out: 'coll2' }], { batchSize: 30 })
1402+
].map(cursor => cursor.toArray())
1403+
);
1404+
})
1405+
.then(() => {
1406+
expect(events)
1407+
.to.be.an('array')
1408+
.with.a.lengthOf(8);
1409+
events.forEach(event => {
1410+
expect(event).to.have.property('commandName', 'aggregate');
1411+
expect(event)
1412+
.to.have.property('command')
1413+
.that.has.property('cursor')
1414+
.that.does.not.have.property('batchSize');
1415+
});
1416+
})
1417+
.catch(_err => {
1418+
err = _err;
1419+
})
1420+
.then(() => client.close())
1421+
.then(() => done(err));
1422+
}
1423+
});
13571424
});

0 commit comments

Comments
 (0)