1
1
'use strict' ;
2
2
3
3
const deprecate = require ( 'util' ) . deprecate ;
4
+ const deprecateOptions = require ( './utils' ) . deprecateOptions ;
4
5
const checkCollectionName = require ( './utils' ) . checkCollectionName ;
5
6
const ObjectID = require ( 'mongodb-core' ) . BSON . ObjectID ;
6
7
const AggregationCursor = require ( './aggregation_cursor' ) ;
@@ -237,7 +238,7 @@ Object.defineProperty(Collection.prototype, 'hint', {
237
238
}
238
239
} ) ;
239
240
240
- const DEPRECATED_FIND_OPTIONS = [ 'maxScan' , 'snapshot' ] ;
241
+ const DEPRECATED_FIND_OPTIONS = [ 'maxScan' , 'fields' , ' snapshot'] ;
241
242
242
243
/**
243
244
* Creates a cursor for a query that can be used to iterate over results from MongoDB
@@ -273,163 +274,163 @@ const DEPRECATED_FIND_OPTIONS = ['maxScan', 'snapshot'];
273
274
* @throws {MongoError }
274
275
* @return {Cursor }
275
276
*/
276
- Collection . prototype . find = function ( query , options , callback ) {
277
- if ( typeof callback === 'object' ) {
278
- // TODO(MAJOR): throw in the future
279
- console . warn ( 'Third parameter to `find()` must be a callback or undefined' ) ;
280
- }
281
-
282
- let selector = query ;
283
- // figuring out arguments
284
- if ( typeof callback !== 'function' ) {
285
- if ( typeof options === 'function' ) {
286
- callback = options ;
287
- options = undefined ;
288
- } else if ( options == null ) {
289
- callback = typeof selector === 'function' ? selector : undefined ;
290
- selector = typeof selector === 'object' ? selector : undefined ;
277
+ Collection . prototype . find = deprecateOptions (
278
+ {
279
+ name : 'collection.find' ,
280
+ deprecatedOptions : DEPRECATED_FIND_OPTIONS ,
281
+ optionsIndex : 1
282
+ } ,
283
+ function ( query , options , callback ) {
284
+ if ( typeof callback === 'object' ) {
285
+ // TODO(MAJOR): throw in the future
286
+ console . warn ( 'Third parameter to `find()` must be a callback or undefined' ) ;
291
287
}
292
- }
293
288
294
- // Ensure selector is not null
295
- selector = selector == null ? { } : selector ;
296
- // Validate correctness off the selector
297
- const object = selector ;
298
- if ( Buffer . isBuffer ( object ) ) {
299
- const object_size = object [ 0 ] | ( object [ 1 ] << 8 ) | ( object [ 2 ] << 16 ) | ( object [ 3 ] << 24 ) ;
300
- if ( object_size !== object . length ) {
301
- const error = new Error (
302
- 'query selector raw message size does not match message header size [' +
303
- object . length +
304
- '] != [' +
305
- object_size +
306
- ']'
307
- ) ;
308
- error . name = 'MongoError' ;
309
- throw error ;
289
+ let selector = query ;
290
+ // figuring out arguments
291
+ if ( typeof callback !== 'function' ) {
292
+ if ( typeof options === 'function' ) {
293
+ callback = options ;
294
+ options = undefined ;
295
+ } else if ( options == null ) {
296
+ callback = typeof selector === 'function' ? selector : undefined ;
297
+ selector = typeof selector === 'object' ? selector : undefined ;
298
+ }
310
299
}
311
- }
312
300
313
- // Check special case where we are using an objectId
314
- if ( selector != null && selector . _bsontype === 'ObjectID' ) {
315
- selector = { _id : selector } ;
316
- }
301
+ // Ensure selector is not null
302
+ selector = selector == null ? { } : selector ;
303
+ // Validate correctness off the selector
304
+ const object = selector ;
305
+ if ( Buffer . isBuffer ( object ) ) {
306
+ const object_size = object [ 0 ] | ( object [ 1 ] << 8 ) | ( object [ 2 ] << 16 ) | ( object [ 3 ] << 24 ) ;
307
+ if ( object_size !== object . length ) {
308
+ const error = new Error (
309
+ 'query selector raw message size does not match message header size [' +
310
+ object . length +
311
+ '] != [' +
312
+ object_size +
313
+ ']'
314
+ ) ;
315
+ error . name = 'MongoError' ;
316
+ throw error ;
317
+ }
318
+ }
317
319
318
- if ( ! options ) options = { } ;
320
+ // Check special case where we are using an objectId
321
+ if ( selector != null && selector . _bsontype === 'ObjectID' ) {
322
+ selector = { _id : selector } ;
323
+ }
319
324
320
- let projection = options . projection || options . fields ;
325
+ if ( ! options ) options = { } ;
321
326
322
- if ( projection && ! Buffer . isBuffer ( projection ) && Array . isArray ( projection ) ) {
323
- projection = projection . length
324
- ? projection . reduce ( ( result , field ) => {
325
- result [ field ] = 1 ;
326
- return result ;
327
- } , { } )
328
- : { _id : 1 } ;
329
- }
327
+ let projection = options . projection || options . fields ;
330
328
331
- // Make a shallow copy of options
332
- let newOptions = Object . assign ( { } , options ) ;
333
-
334
- // Make a shallow copy of the collection options
335
- for ( let key in this . s . options ) {
336
- if ( mergeKeys . indexOf ( key ) !== - 1 ) {
337
- newOptions [ key ] = this . s . options [ key ] ;
329
+ if ( projection && ! Buffer . isBuffer ( projection ) && Array . isArray ( projection ) ) {
330
+ projection = projection . length
331
+ ? projection . reduce ( ( result , field ) => {
332
+ result [ field ] = 1 ;
333
+ return result ;
334
+ } , { } )
335
+ : { _id : 1 } ;
338
336
}
339
- }
340
-
341
- // Unpack options
342
- newOptions . skip = options . skip ? options . skip : 0 ;
343
- newOptions . limit = options . limit ? options . limit : 0 ;
344
- newOptions . raw = typeof options . raw === 'boolean' ? options . raw : this . s . raw ;
345
- newOptions . hint = options . hint != null ? normalizeHintField ( options . hint ) : this . s . collectionHint ;
346
- newOptions . timeout = typeof options . timeout === 'undefined' ? undefined : options . timeout ;
347
- // // If we have overridden slaveOk otherwise use the default db setting
348
- newOptions . slaveOk = options . slaveOk != null ? options . slaveOk : this . s . db . slaveOk ;
349
-
350
- // Add read preference if needed
351
- newOptions . readPreference = resolveReadPreference ( newOptions , {
352
- db : this . s . db ,
353
- collection : this
354
- } ) ;
355
337
356
- // Set slave ok to true if read preference different from primary
357
- if (
358
- newOptions . readPreference != null &&
359
- ( newOptions . readPreference !== 'primary' || newOptions . readPreference . mode !== 'primary' )
360
- ) {
361
- newOptions . slaveOk = true ;
362
- }
338
+ // Make a shallow copy of options
339
+ let newOptions = Object . assign ( { } , options ) ;
363
340
364
- // Ensure the query is an object
365
- if ( selector != null && typeof selector !== 'object' ) {
366
- throw MongoError . create ( { message : 'query selector must be an object' , driver : true } ) ;
367
- }
341
+ // Make a shallow copy of the collection options
342
+ for ( let key in this . s . options ) {
343
+ if ( mergeKeys . indexOf ( key ) !== - 1 ) {
344
+ newOptions [ key ] = this . s . options [ key ] ;
345
+ }
346
+ }
368
347
369
- // Build the find command
370
- const findCommand = {
371
- find : this . s . namespace ,
372
- limit : newOptions . limit ,
373
- skip : newOptions . skip ,
374
- query : selector
375
- } ;
348
+ // Unpack options
349
+ newOptions . skip = options . skip ? options . skip : 0 ;
350
+ newOptions . limit = options . limit ? options . limit : 0 ;
351
+ newOptions . raw = typeof options . raw === 'boolean' ? options . raw : this . s . raw ;
352
+ newOptions . hint =
353
+ options . hint != null ? normalizeHintField ( options . hint ) : this . s . collectionHint ;
354
+ newOptions . timeout = typeof options . timeout === 'undefined' ? undefined : options . timeout ;
355
+ // // If we have overridden slaveOk otherwise use the default db setting
356
+ newOptions . slaveOk = options . slaveOk != null ? options . slaveOk : this . s . db . slaveOk ;
357
+
358
+ // Add read preference if needed
359
+ newOptions . readPreference = resolveReadPreference ( newOptions , {
360
+ db : this . s . db ,
361
+ collection : this
362
+ } ) ;
376
363
377
- // Ensure we use the right await data option
378
- if ( typeof newOptions . awaitdata === 'boolean' ) {
379
- newOptions . awaitData = newOptions . awaitdata ;
380
- }
364
+ // Set slave ok to true if read preference different from primary
365
+ if (
366
+ newOptions . readPreference != null &&
367
+ ( newOptions . readPreference !== 'primary' || newOptions . readPreference . mode !== 'primary' )
368
+ ) {
369
+ newOptions . slaveOk = true ;
370
+ }
381
371
382
- // Translate to new command option noCursorTimeout
383
- if ( typeof newOptions . timeout === 'boolean' ) newOptions . noCursorTimeout = newOptions . timeout ;
372
+ // Ensure the query is an object
373
+ if ( selector != null && typeof selector !== 'object' ) {
374
+ throw MongoError . create ( { message : 'query selector must be an object' , driver : true } ) ;
375
+ }
384
376
385
- // Merge in options to command
386
- for ( let name in newOptions ) {
387
- if ( newOptions [ name ] != null && name !== 'session' ) {
388
- findCommand [ name ] = newOptions [ name ] ;
377
+ // Build the find command
378
+ const findCommand = {
379
+ find : this . s . namespace ,
380
+ limit : newOptions . limit ,
381
+ skip : newOptions . skip ,
382
+ query : selector
383
+ } ;
384
+
385
+ // Ensure we use the right await data option
386
+ if ( typeof newOptions . awaitdata === 'boolean' ) {
387
+ newOptions . awaitData = newOptions . awaitdata ;
389
388
}
390
- }
391
389
392
- DEPRECATED_FIND_OPTIONS . forEach ( deprecatedOption => {
393
- if ( findCommand [ deprecatedOption ] ) {
394
- console . warn (
395
- `Find option ${ deprecatedOption } is deprecated, and will be removed in a later version`
396
- ) ;
390
+ // Translate to new command option noCursorTimeout
391
+ if ( typeof newOptions . timeout === 'boolean' ) newOptions . noCursorTimeout = newOptions . timeout ;
392
+
393
+ // Merge in options to command
394
+ for ( let name in newOptions ) {
395
+ if ( newOptions [ name ] != null && name !== 'session' ) {
396
+ findCommand [ name ] = newOptions [ name ] ;
397
+ }
397
398
}
398
- } ) ;
399
399
400
- if ( projection ) findCommand . fields = projection ;
400
+ if ( projection ) findCommand . fields = projection ;
401
401
402
- // Add db object to the new options
403
- newOptions . db = this . s . db ;
402
+ // Add db object to the new options
403
+ newOptions . db = this . s . db ;
404
404
405
- // Add the promise library
406
- newOptions . promiseLibrary = this . s . promiseLibrary ;
405
+ // Add the promise library
406
+ newOptions . promiseLibrary = this . s . promiseLibrary ;
407
407
408
- // Set raw if available at collection level
409
- if ( newOptions . raw == null && typeof this . s . raw === 'boolean' ) newOptions . raw = this . s . raw ;
410
- // Set promoteLongs if available at collection level
411
- if ( newOptions . promoteLongs == null && typeof this . s . promoteLongs === 'boolean' )
412
- newOptions . promoteLongs = this . s . promoteLongs ;
413
- if ( newOptions . promoteValues == null && typeof this . s . promoteValues === 'boolean' )
414
- newOptions . promoteValues = this . s . promoteValues ;
415
- if ( newOptions . promoteBuffers == null && typeof this . s . promoteBuffers === 'boolean' )
416
- newOptions . promoteBuffers = this . s . promoteBuffers ;
408
+ // Set raw if available at collection level
409
+ if ( newOptions . raw == null && typeof this . s . raw === 'boolean' ) newOptions . raw = this . s . raw ;
410
+ // Set promoteLongs if available at collection level
411
+ if ( newOptions . promoteLongs == null && typeof this . s . promoteLongs === 'boolean' )
412
+ newOptions . promoteLongs = this . s . promoteLongs ;
413
+ if ( newOptions . promoteValues == null && typeof this . s . promoteValues === 'boolean' )
414
+ newOptions . promoteValues = this . s . promoteValues ;
415
+ if ( newOptions . promoteBuffers == null && typeof this . s . promoteBuffers === 'boolean' )
416
+ newOptions . promoteBuffers = this . s . promoteBuffers ;
417
417
418
- // Sort options
419
- if ( findCommand . sort ) {
420
- findCommand . sort = formattedOrderClause ( findCommand . sort ) ;
421
- }
418
+ // Sort options
419
+ if ( findCommand . sort ) {
420
+ findCommand . sort = formattedOrderClause ( findCommand . sort ) ;
421
+ }
422
422
423
- // Set the readConcern
424
- decorateWithReadConcern ( findCommand , this , options ) ;
423
+ // Set the readConcern
424
+ decorateWithReadConcern ( findCommand , this , options ) ;
425
425
426
- // Decorate find command with collation options
427
- decorateWithCollation ( findCommand , this , options ) ;
426
+ // Decorate find command with collation options
427
+ decorateWithCollation ( findCommand , this , options ) ;
428
428
429
- const cursor = this . s . topology . cursor ( this . s . namespace , findCommand , newOptions ) ;
429
+ const cursor = this . s . topology . cursor ( this . s . namespace , findCommand , newOptions ) ;
430
430
431
- return typeof callback === 'function' ? handleCallback ( callback , null , cursor ) : cursor ;
432
- } ;
431
+ return typeof callback === 'function' ? handleCallback ( callback , null , cursor ) : cursor ;
432
+ }
433
+ ) ;
433
434
434
435
/**
435
436
* Inserts a single document into MongoDB. If documents passed in do not contain the **_id** field,
@@ -662,7 +663,7 @@ Collection.prototype.bulkWrite = function(operations, options, callback) {
662
663
* @return {Promise } returns Promise if no callback passed
663
664
* @deprecated Use insertOne, insertMany or bulkWrite
664
665
*/
665
- Collection . prototype . insert = function ( docs , options , callback ) {
666
+ Collection . prototype . insert = deprecate ( function ( docs , options , callback ) {
666
667
if ( typeof options === 'function' ) ( callback = options ) , ( options = { } ) ;
667
668
options = options || { ordered : false } ;
668
669
docs = ! Array . isArray ( docs ) ? [ docs ] : docs ;
@@ -672,7 +673,7 @@ Collection.prototype.insert = function(docs, options, callback) {
672
673
}
673
674
674
675
return this . insertMany ( docs , options , callback ) ;
675
- } ;
676
+ } , 'collection.insert is deprecated. Use insertOne, insertMany or bulkWrite instead.' ) ;
676
677
677
678
/**
678
679
* @typedef {Object } Collection~updateWriteOpResult
@@ -816,7 +817,7 @@ Collection.prototype.updateMany = function(filter, update, options, callback) {
816
817
* @return {Promise } returns Promise if no callback passed
817
818
* @deprecated use updateOne, updateMany or bulkWrite
818
819
*/
819
- Collection . prototype . update = function ( selector , document , options , callback ) {
820
+ Collection . prototype . update = deprecate ( function ( selector , document , options , callback ) {
820
821
if ( typeof options === 'function' ) ( callback = options ) , ( options = { } ) ;
821
822
options = options || { } ;
822
823
@@ -833,7 +834,7 @@ Collection.prototype.update = function(selector, document, options, callback) {
833
834
options ,
834
835
callback
835
836
] ) ;
836
- } ;
837
+ } , 'collection.update is deprecated. Use updateOne, updateMany, or bulkWrite instead.' ) ;
837
838
838
839
/**
839
840
* @typedef {Object } Collection~deleteWriteOpResult
@@ -919,7 +920,7 @@ Collection.prototype.removeMany = Collection.prototype.deleteMany;
919
920
* @return {Promise } returns Promise if no callback passed
920
921
* @deprecated use deleteOne, deleteMany or bulkWrite
921
922
*/
922
- Collection . prototype . remove = function ( selector , options , callback ) {
923
+ Collection . prototype . remove = deprecate ( function ( selector , options , callback ) {
923
924
if ( typeof options === 'function' ) ( callback = options ) , ( options = { } ) ;
924
925
options = options || { } ;
925
926
@@ -930,7 +931,7 @@ Collection.prototype.remove = function(selector, options, callback) {
930
931
}
931
932
932
933
return executeOperation ( this . s . topology , removeDocuments , [ this , selector , options , callback ] ) ;
933
- } ;
934
+ } , 'collection.remove is deprecated. Use deleteOne, deleteMany, or bulkWrite instead.' ) ;
934
935
935
936
/**
936
937
* Save a document. Simple full document replacement function. Not recommended for efficiency, use atomic
@@ -946,7 +947,7 @@ Collection.prototype.remove = function(selector, options, callback) {
946
947
* @return {Promise } returns Promise if no callback passed
947
948
* @deprecated use insertOne, insertMany, updateOne or updateMany
948
949
*/
949
- Collection . prototype . save = function ( doc , options , callback ) {
950
+ Collection . prototype . save = deprecate ( function ( doc , options , callback ) {
950
951
if ( typeof options === 'function' ) ( callback = options ) , ( options = { } ) ;
951
952
options = options || { } ;
952
953
@@ -957,7 +958,7 @@ Collection.prototype.save = function(doc, options, callback) {
957
958
}
958
959
959
960
return executeOperation ( this . s . topology , save , [ this , doc , options , callback ] ) ;
960
- } ;
961
+ } , 'collection.save is deprecated. Use insertOne, insertMany, updateOne, or updateMany instead.' ) ;
961
962
962
963
/**
963
964
* The callback format for results
@@ -1007,19 +1008,26 @@ Collection.prototype.save = function(doc, options, callback) {
1007
1008
* @param {Collection~resultCallback } [callback] The command result callback
1008
1009
* @return {Promise } returns Promise if no callback passed
1009
1010
*/
1010
- Collection . prototype . findOne = function ( query , options , callback ) {
1011
- if ( typeof callback === 'object' ) {
1012
- // TODO(MAJOR): throw in the future
1013
- console . warn ( 'Third parameter to `findOne()` must be a callback or undefined' ) ;
1014
- }
1011
+ Collection . prototype . findOne = deprecateOptions (
1012
+ {
1013
+ name : 'collection.find' ,
1014
+ deprecatedOptions : DEPRECATED_FIND_OPTIONS ,
1015
+ optionsIndex : 1
1016
+ } ,
1017
+ function ( query , options , callback ) {
1018
+ if ( typeof callback === 'object' ) {
1019
+ // TODO(MAJOR): throw in the future
1020
+ console . warn ( 'Third parameter to `findOne()` must be a callback or undefined' ) ;
1021
+ }
1015
1022
1016
- if ( typeof query === 'function' ) ( callback = query ) , ( query = { } ) , ( options = { } ) ;
1017
- if ( typeof options === 'function' ) ( callback = options ) , ( options = { } ) ;
1018
- query = query || { } ;
1019
- options = options || { } ;
1023
+ if ( typeof query === 'function' ) ( callback = query ) , ( query = { } ) , ( options = { } ) ;
1024
+ if ( typeof options === 'function' ) ( callback = options ) , ( options = { } ) ;
1025
+ query = query || { } ;
1026
+ options = options || { } ;
1020
1027
1021
- return executeOperation ( this . s . topology , findOne , [ this , query , options , callback ] ) ;
1022
- } ;
1028
+ return executeOperation ( this . s . topology , findOne , [ this , query , options , callback ] ) ;
1029
+ }
1030
+ ) ;
1023
1031
1024
1032
/**
1025
1033
* The callback format for the collection method, must be used if strict is specified
@@ -1197,7 +1205,10 @@ Collection.prototype.dropIndexes = function(options, callback) {
1197
1205
* @param {Collection~resultCallback } callback The command result callback
1198
1206
* @return {Promise } returns Promise if no [callback] passed
1199
1207
*/
1200
- Collection . prototype . dropAllIndexes = Collection . prototype . dropIndexes ;
1208
+ Collection . prototype . dropAllIndexes = deprecate (
1209
+ Collection . prototype . dropIndexes ,
1210
+ 'collection.dropAllIndexes is deprecated. Use dropIndexes instead.'
1211
+ ) ;
1201
1212
1202
1213
/**
1203
1214
* Reindex all indexes on the collection
@@ -1290,12 +1301,12 @@ Collection.prototype.listIndexes = function(options) {
1290
1301
* @param {Collection~resultCallback } [callback] The command result callback
1291
1302
* @return {Promise } returns Promise if no callback passed
1292
1303
*/
1293
- Collection . prototype . ensureIndex = function ( fieldOrSpec , options , callback ) {
1304
+ Collection . prototype . ensureIndex = deprecate ( function ( fieldOrSpec , options , callback ) {
1294
1305
if ( typeof options === 'function' ) ( callback = options ) , ( options = { } ) ;
1295
1306
options = options || { } ;
1296
1307
1297
1308
return executeOperation ( this . s . topology , ensureIndex , [ this , fieldOrSpec , options , callback ] ) ;
1298
- } ;
1309
+ } , 'collection.ensureIndex is deprecated. Use createIndexes instead.' ) ;
1299
1310
1300
1311
/**
1301
1312
* Checks if one or more indexes exist on the collection, fails on first non-existing index
@@ -1634,7 +1645,7 @@ Collection.prototype.findOneAndUpdate = function(filter, update, options, callba
1634
1645
* @return {Promise } returns Promise if no callback passed
1635
1646
* @deprecated use findOneAndUpdate, findOneAndReplace or findOneAndDelete instead
1636
1647
*/
1637
- Collection . prototype . findAndModify = function ( query , sort , doc , options , callback ) {
1648
+ Collection . prototype . findAndModify = deprecate ( function ( query , sort , doc , options , callback ) {
1638
1649
const args = Array . prototype . slice . call ( arguments , 1 ) ;
1639
1650
callback = typeof args [ args . length - 1 ] === 'function' ? args . pop ( ) : undefined ;
1640
1651
sort = args . length ? args . shift ( ) || [ ] : [ ] ;
@@ -1654,7 +1665,7 @@ Collection.prototype.findAndModify = function(query, sort, doc, options, callbac
1654
1665
options ,
1655
1666
callback
1656
1667
] ) ;
1657
- } ;
1668
+ } , 'collection.findAndModify is deprecated. Use findOneAndUpdate, findOneAndReplace or findOneAndDelete instead.' ) ;
1658
1669
1659
1670
/**
1660
1671
* Find and remove a document.
@@ -1670,14 +1681,14 @@ Collection.prototype.findAndModify = function(query, sort, doc, options, callbac
1670
1681
* @return {Promise } returns Promise if no callback passed
1671
1682
* @deprecated use findOneAndDelete instead
1672
1683
*/
1673
- Collection . prototype . findAndRemove = function ( query , sort , options , callback ) {
1684
+ Collection . prototype . findAndRemove = deprecate ( function ( query , sort , options , callback ) {
1674
1685
const args = Array . prototype . slice . call ( arguments , 1 ) ;
1675
1686
callback = typeof args [ args . length - 1 ] === 'function' ? args . pop ( ) : undefined ;
1676
1687
sort = args . length ? args . shift ( ) || [ ] : [ ] ;
1677
1688
options = args . length ? args . shift ( ) || { } : { } ;
1678
1689
1679
1690
return executeOperation ( this . s . topology , findAndRemove , [ this , query , sort , options , callback ] ) ;
1680
- } ;
1691
+ } , 'collection.findAndRemove is deprecated. Use findOneAndDelete instead.' ) ;
1681
1692
1682
1693
/**
1683
1694
* Execute an aggregation framework pipeline against the collection, needs MongoDB >= 2.2
@@ -1933,9 +1944,9 @@ Collection.prototype.geoHaystackSearch = function(x, y, options, callback) {
1933
1944
* @param {ClientSession } [options.session] optional session to use for this operation
1934
1945
* @param {Collection~resultCallback } [callback] The command result callback
1935
1946
* @return {Promise } returns Promise if no callback passed
1936
- * @deprecated MongoDB 3.6 or higher will no longer support the group command. We recommend rewriting using the aggregation framework.
1947
+ * @deprecated MongoDB 3.6 or higher no longer supports the group command. We recommend rewriting using the aggregation framework.
1937
1948
*/
1938
- Collection . prototype . group = function (
1949
+ Collection . prototype . group = deprecate ( function (
1939
1950
keys ,
1940
1951
condition ,
1941
1952
initial ,
@@ -1989,7 +2000,8 @@ Collection.prototype.group = function(
1989
2000
options ,
1990
2001
callback
1991
2002
] ) ;
1992
- } ;
2003
+ } ,
2004
+ 'MongoDB 3.6 or higher no longer supports the group command. We recommend rewriting using the aggregation framework.' ) ;
1993
2005
1994
2006
/**
1995
2007
* Run Map Reduce across a collection. Be aware that the inline option for out will return an array of results not a collection.
0 commit comments