Skip to content

Commit d2d0367

Browse files
committed
feat(listCollections): add support for nameOnly option
Fixes NODE-1471
1 parent 552c50a commit d2d0367

File tree

2 files changed

+97
-3
lines changed

2 files changed

+97
-3
lines changed

lib/db.js

+11-3
Original file line numberDiff line numberDiff line change
@@ -455,8 +455,10 @@ Db.prototype.collection = function(name, options, callback) {
455455
return callback(new MongoError('topology was destroyed'));
456456
}
457457

458+
const listCollectionOptions = Object.assign({}, options, { nameOnly: true });
459+
458460
// Strict mode
459-
this.listCollections({ name: name }, options).toArray(function(err, collections) {
461+
this.listCollections({ name: name }, listCollectionOptions).toArray(function(err, collections) {
460462
if (err != null) return handleCallback(callback, err, null);
461463
if (collections.length === 0)
462464
return handleCallback(
@@ -486,9 +488,11 @@ var createCollection = function(self, name, options, callback) {
486488
return callback(new MongoError('topology was destroyed'));
487489
}
488490

491+
const listCollectionOptions = Object.assign({}, finalOptions, { nameOnly: true });
492+
489493
// Check if we have the name
490494
self
491-
.listCollections({ name: name }, finalOptions)
495+
.listCollections({ name: name }, listCollectionOptions)
492496
.setReadPreference(ReadPreference.PRIMARY)
493497
.toArray(function(err, collections) {
494498
if (err != null) return handleCallback(callback, err, null);
@@ -653,6 +657,7 @@ var listCollectionsTranforms = function(databaseName) {
653657
* @method
654658
* @param {object} [filter={}] Query to filter collections by
655659
* @param {object} [options=null] Optional settings.
660+
* @param {boolean} [options.nameOnly=false] Since 4.0: If true, will only return the collection name in the response, and will omit additional info
656661
* @param {number} [options.batchSize=null] The batchSize for the returned command cursor or if pre 2.8 the systems batch collection
657662
* @param {(ReadPreference|string)} [options.readPreference=null] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
658663
* @param {ClientSession} [options.session] optional session to use for this operation
@@ -678,8 +683,10 @@ Db.prototype.listCollections = function(filter, options) {
678683
if (this.serverConfig.capabilities().hasListCollectionsCommand) {
679684
// Cursor options
680685
var cursor = options.batchSize ? { batchSize: options.batchSize } : {};
686+
687+
const nameOnly = typeof options.nameOnly === 'boolean' ? options.nameOnly : false;
681688
// Build the command
682-
var command = { listCollections: true, filter: filter, cursor: cursor };
689+
var command = { listCollections: true, filter, cursor, nameOnly };
683690
// Set the AggregationCursor constructor
684691
options.cursorFactory = CommandCursor;
685692
// Create the cursor
@@ -917,6 +924,7 @@ Db.prototype.collections = function(options, callback) {
917924
};
918925

919926
var collections = function(self, options, callback) {
927+
options = Object.assign({}, options, { nameOnly: true });
920928
// Let's get the collection names
921929
self.listCollections({}, options).toArray(function(err, documents) {
922930
if (err != null) return handleCallback(callback, err, null);
+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
'use strict';
2+
3+
const mock = require('mongodb-mock-server');
4+
const expect = require('chai').expect;
5+
const MongoClient = require('../../lib/mongo_client');
6+
7+
describe('db.listCollections', function() {
8+
const testHarness = {};
9+
afterEach(() => mock.cleanup());
10+
beforeEach(() => {
11+
return mock.createServer().then(server => {
12+
server.setMessageHandler(request => {
13+
const doc = request.document;
14+
15+
if (doc.ismaster) {
16+
return request.reply(Object.assign({}, mock.DEFAULT_ISMASTER));
17+
}
18+
19+
if (doc.listCollections) {
20+
return request.reply({
21+
ok: 1,
22+
cursor: {
23+
id: 0,
24+
ns: 'test.$cmd.listCollections',
25+
firstBatch: [{ name: 'test', type: 'collection' }]
26+
}
27+
});
28+
}
29+
});
30+
testHarness.server = server;
31+
});
32+
});
33+
34+
[
35+
{
36+
description: 'should always send nameOnly option, defaulting to false',
37+
command: db => db.listCollections().toArray(() => {}),
38+
listCollectionsValue: false
39+
},
40+
{
41+
description: 'should propagate the nameOnly option',
42+
command: db => db.listCollections({}, { nameOnly: true }).toArray(() => {}),
43+
listCollectionsValue: true
44+
},
45+
{
46+
description: 'should send nameOnly: true for db.createCollection',
47+
command: db => db.createCollection('foo', () => {}),
48+
listCollectionsValue: true
49+
},
50+
{
51+
description: 'should send nameOnly: true for db.collections',
52+
command: db => db.collections(() => {}),
53+
listCollectionsValue: true
54+
},
55+
{
56+
description: 'should send nameOnly: true for db.collection',
57+
command: db => db.collection('foo', { strict: true }, () => {}),
58+
listCollectionsValue: true
59+
}
60+
].forEach(config => {
61+
function testFn(done) {
62+
const client = new MongoClient(`mongodb://${testHarness.server.uri()}/test`, {
63+
monitorCommands: true
64+
});
65+
66+
client.connect((err, client) => {
67+
const db = client.db('foo');
68+
69+
client.on('commandStarted', e => {
70+
if (e.commandName === 'listCollections') {
71+
try {
72+
expect(e).to.have.nested.property('command.nameOnly', config.listCollectionsValue);
73+
client.close(done);
74+
} catch (err) {
75+
client.close(() => done(err));
76+
}
77+
}
78+
});
79+
80+
config.command(db);
81+
});
82+
}
83+
84+
it(config.description, { test: testFn, metadata: { requires: { mongodb: '>=2.7.6' } } });
85+
});
86+
});

0 commit comments

Comments
 (0)