mongodb 3.6.3 → 3.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/HISTORY.md +27 -1
  2. package/README.md +1 -3
  3. package/lib/admin.js +10 -8
  4. package/lib/aggregation_cursor.js +7 -1
  5. package/lib/bulk/common.js +5 -4
  6. package/lib/collection.js +111 -65
  7. package/lib/core/cursor.js +4 -1
  8. package/lib/core/sdam/monitor.js +14 -11
  9. package/lib/core/sdam/topology.js +2 -1
  10. package/lib/core/topologies/mongos.js +2 -1
  11. package/lib/core/topologies/replset.js +13 -7
  12. package/lib/core/topologies/server.js +3 -2
  13. package/lib/core/uri_parser.js +18 -2
  14. package/lib/core/wireprotocol/query.js +12 -11
  15. package/lib/core/wireprotocol/write_command.js +10 -1
  16. package/lib/cursor.js +15 -13
  17. package/lib/db.js +43 -27
  18. package/lib/explain.js +55 -0
  19. package/lib/gridfs/grid_store.js +13 -9
  20. package/lib/gridfs-stream/upload.js +5 -3
  21. package/lib/mongo_client.js +10 -8
  22. package/lib/operations/aggregate.js +5 -7
  23. package/lib/operations/command_v2.js +10 -1
  24. package/lib/operations/common_functions.js +14 -27
  25. package/lib/operations/connect.js +30 -7
  26. package/lib/operations/delete_many.js +15 -2
  27. package/lib/operations/delete_one.js +15 -2
  28. package/lib/operations/distinct.js +10 -2
  29. package/lib/operations/find.js +7 -1
  30. package/lib/operations/find_and_modify.js +14 -1
  31. package/lib/operations/find_one.js +4 -0
  32. package/lib/operations/map_reduce.js +20 -1
  33. package/lib/operations/operation.js +11 -1
  34. package/lib/operations/update_many.js +23 -2
  35. package/lib/operations/update_one.js +22 -16
  36. package/lib/url_parser.js +19 -14
  37. package/lib/utils.js +22 -2
  38. package/lib/write_concern.js +18 -4
  39. package/package.json +3 -2
@@ -118,7 +118,8 @@ class Monitor extends EventEmitter {
118
118
  }
119
119
 
120
120
  reset() {
121
- if (isInCloseState(this)) {
121
+ const topologyVersion = this[kServer].description.topologyVersion;
122
+ if (isInCloseState(this) || topologyVersion == null) {
122
123
  return;
123
124
  }
124
125
 
@@ -152,7 +153,6 @@ class Monitor extends EventEmitter {
152
153
  }
153
154
 
154
155
  function resetMonitorState(monitor) {
155
- stateTransition(monitor, STATE_CLOSING);
156
156
  if (monitor[kMonitorId]) {
157
157
  monitor[kMonitorId].stop();
158
158
  monitor[kMonitorId] = null;
@@ -200,16 +200,19 @@ function checkServer(monitor, callback) {
200
200
  const topologyVersion = monitor[kServer].description.topologyVersion;
201
201
  const isAwaitable = topologyVersion != null;
202
202
 
203
- const cmd = isAwaitable
204
- ? { ismaster: true, maxAwaitTimeMS, topologyVersion: makeTopologyVersion(topologyVersion) }
205
- : { ismaster: true };
206
-
207
- const options = isAwaitable
208
- ? { socketTimeout: connectTimeoutMS + maxAwaitTimeMS, exhaustAllowed: true }
209
- : { socketTimeout: connectTimeoutMS };
203
+ const cmd = { ismaster: true };
204
+ const options = { socketTimeout: connectTimeoutMS };
210
205
 
211
- if (isAwaitable && monitor[kRTTPinger] == null) {
212
- monitor[kRTTPinger] = new RTTPinger(monitor[kCancellationToken], monitor.connectOptions);
206
+ if (isAwaitable) {
207
+ cmd.maxAwaitTimeMS = maxAwaitTimeMS;
208
+ cmd.topologyVersion = makeTopologyVersion(topologyVersion);
209
+ if (connectTimeoutMS) {
210
+ options.socketTimeout = connectTimeoutMS + maxAwaitTimeMS;
211
+ }
212
+ options.exhaustAllowed = true;
213
+ if (monitor[kRTTPinger] == null) {
214
+ monitor[kRTTPinger] = new RTTPinger(monitor[kCancellationToken], monitor.connectOptions);
215
+ }
213
216
  }
214
217
 
215
218
  monitor[kConnection].command('admin.$cmd', cmd, options, (err, result) => {
@@ -930,7 +930,8 @@ function executeWriteOperation(args, options, callback) {
930
930
  !!options.retryWrites &&
931
931
  options.session &&
932
932
  isRetryableWritesSupported(topology) &&
933
- !options.session.inTransaction();
933
+ !options.session.inTransaction() &&
934
+ options.explain === undefined;
934
935
 
935
936
  topology.selectServer(writableServerSelector(), options, (err, server) => {
936
937
  if (err) {
@@ -919,7 +919,8 @@ function executeWriteOperation(args, options, callback) {
919
919
  !!options.retryWrites &&
920
920
  options.session &&
921
921
  isRetryableWritesSupported(self) &&
922
- !options.session.inTransaction();
922
+ !options.session.inTransaction() &&
923
+ options.explain === undefined;
923
924
 
924
925
  const handler = (err, result) => {
925
926
  if (!err) return callback(null, result);
@@ -541,7 +541,7 @@ var monitorServer = function(host, self, options) {
541
541
  self.s.options.secondaryOnlyConnectionAllowed) ||
542
542
  self.s.replicaSetState.hasPrimary())
543
543
  ) {
544
- self.state = CONNECTED;
544
+ stateTransition(self, CONNECTED);
545
545
 
546
546
  // Emit connected sign
547
547
  process.nextTick(function() {
@@ -558,7 +558,7 @@ var monitorServer = function(host, self, options) {
558
558
  self.s.options.secondaryOnlyConnectionAllowed) ||
559
559
  self.s.replicaSetState.hasPrimary())
560
560
  ) {
561
- self.state = CONNECTED;
561
+ stateTransition(self, CONNECTED);
562
562
 
563
563
  // Rexecute any stalled operation
564
564
  rexecuteOperations(self);
@@ -787,7 +787,7 @@ function handleInitialConnectEvent(self, event) {
787
787
  // Do we have a primary or primaryAndSecondary
788
788
  if (shouldTriggerConnect(self)) {
789
789
  // We are connected
790
- self.state = CONNECTED;
790
+ stateTransition(self, CONNECTED);
791
791
 
792
792
  // Set initial connect state
793
793
  self.initialConnectState.connect = true;
@@ -975,14 +975,19 @@ ReplSet.prototype.destroy = function(options, callback) {
975
975
  // Emit toplogy closing event
976
976
  emitSDAMEvent(this, 'topologyClosed', { topologyId: this.id });
977
977
 
978
- // Transition state
979
- stateTransition(this, DESTROYED);
980
-
981
978
  if (typeof callback === 'function') {
982
979
  callback(null, null);
983
980
  }
984
981
  };
985
982
 
983
+ if (this.state === DESTROYED) {
984
+ if (typeof callback === 'function') callback(null, null);
985
+ return;
986
+ }
987
+
988
+ // Transition state
989
+ stateTransition(this, DESTROYED);
990
+
986
991
  // Clear out any monitoring process
987
992
  if (this.haTimeoutId) clearTimeout(this.haTimeoutId);
988
993
 
@@ -1188,7 +1193,8 @@ function executeWriteOperation(args, options, callback) {
1188
1193
  !!options.retryWrites &&
1189
1194
  options.session &&
1190
1195
  isRetryableWritesSupported(self) &&
1191
- !options.session.inTransaction();
1196
+ !options.session.inTransaction() &&
1197
+ options.explain === undefined;
1192
1198
 
1193
1199
  if (!self.s.replicaSetState.hasPrimary()) {
1194
1200
  if (self.s.disconnectHandler) {
@@ -864,12 +864,14 @@ Server.prototype.destroy = function(options, callback) {
864
864
  }
865
865
 
866
866
  // No pool, return
867
- if (!self.s.pool) {
867
+ if (!self.s.pool || this._destroyed) {
868
868
  this._destroyed = true;
869
869
  if (typeof callback === 'function') callback(null, null);
870
870
  return;
871
871
  }
872
872
 
873
+ this._destroyed = true;
874
+
873
875
  // Emit close event
874
876
  if (options.emitClose) {
875
877
  self.emit('close', self);
@@ -900,7 +902,6 @@ Server.prototype.destroy = function(options, callback) {
900
902
 
901
903
  // Destroy the pool
902
904
  this.s.pool.destroy(options.force, callback);
903
- this._destroyed = true;
904
905
  };
905
906
 
906
907
  /**
@@ -11,6 +11,11 @@ const ReadPreference = require('./topologies/read_preference');
11
11
  */
12
12
  const HOSTS_RX = /(mongodb(?:\+srv|)):\/\/(?: (?:[^:]*) (?: : ([^@]*) )? @ )?([^/?]*)(?:\/|)(.*)/;
13
13
 
14
+ // Options that reference file paths should not be parsed
15
+ const FILE_PATH_OPTIONS = new Set(
16
+ ['sslCA', 'sslCert', 'sslKey', 'tlsCAFile', 'tlsCertificateKeyFile'].map(key => key.toLowerCase())
17
+ );
18
+
14
19
  /**
15
20
  * Determines whether a provided address matches the provided parent domain in order
16
21
  * to avoid certain attack vectors.
@@ -86,7 +91,7 @@ function parseSrvConnectionString(uri, options, callback) {
86
91
  // Resolve TXT record and add options from there if they exist.
87
92
  dns.resolveTxt(lookupAddress, (err, record) => {
88
93
  if (err) {
89
- if (err.code !== 'ENODATA') {
94
+ if (err.code !== 'ENODATA' && err.code !== 'ENOTFOUND') {
90
95
  return callback(err);
91
96
  }
92
97
  record = null;
@@ -424,7 +429,9 @@ function parseQueryString(query, options) {
424
429
  }
425
430
 
426
431
  const normalizedKey = key.toLowerCase();
427
- const parsedValue = parseQueryStringItemValue(normalizedKey, value);
432
+ const parsedValue = FILE_PATH_OPTIONS.has(normalizedKey)
433
+ ? value
434
+ : parseQueryStringItemValue(normalizedKey, value);
428
435
  applyConnectionStringOption(result, normalizedKey, parsedValue, options);
429
436
  }
430
437
 
@@ -687,6 +694,15 @@ function parseConnectionString(uri, options, callback) {
687
694
  return callback(new MongoParseError('directConnection option requires exactly one host'));
688
695
  }
689
696
 
697
+ // NOTE: this behavior will go away in v4.0, we will always auto discover there
698
+ if (
699
+ parsedOptions.directConnection == null &&
700
+ hosts.length === 1 &&
701
+ parsedOptions.replicaSet == null
702
+ ) {
703
+ parsedOptions.directConnection = true;
704
+ }
705
+
690
706
  const result = {
691
707
  hosts: hosts,
692
708
  auth: auth.db || auth.username ? auth : null,
@@ -8,6 +8,8 @@ const isSharded = require('./shared').isSharded;
8
8
  const maxWireVersion = require('../utils').maxWireVersion;
9
9
  const applyCommonQueryOptions = require('./shared').applyCommonQueryOptions;
10
10
  const command = require('./command');
11
+ const decorateWithExplain = require('../../utils').decorateWithExplain;
12
+ const Explain = require('../../explain').Explain;
11
13
 
12
14
  function query(server, ns, cmd, cursorState, options, callback) {
13
15
  options = options || {};
@@ -31,7 +33,14 @@ function query(server, ns, cmd, cursorState, options, callback) {
31
33
  }
32
34
 
33
35
  const readPreference = getReadPreference(cmd, options);
34
- const findCmd = prepareFindCommand(server, ns, cmd, cursorState, options);
36
+ let findCmd = prepareFindCommand(server, ns, cmd, cursorState, options);
37
+
38
+ // If we have explain, we need to rewrite the find command
39
+ // to wrap it in the explain command
40
+ const explain = Explain.fromOptions(options);
41
+ if (explain) {
42
+ findCmd = decorateWithExplain(findCmd, explain);
43
+ }
35
44
 
36
45
  // NOTE: This actually modifies the passed in cmd, and our code _depends_ on this
37
46
  // side-effect. Change this ASAP
@@ -59,7 +68,7 @@ function query(server, ns, cmd, cursorState, options, callback) {
59
68
 
60
69
  function prepareFindCommand(server, ns, cmd, cursorState) {
61
70
  cursorState.batchSize = cmd.batchSize || cursorState.batchSize;
62
- let findCmd = {
71
+ const findCmd = {
63
72
  find: collectionNamespace(ns)
64
73
  };
65
74
 
@@ -143,14 +152,6 @@ function prepareFindCommand(server, ns, cmd, cursorState) {
143
152
  if (cmd.collation) findCmd.collation = cmd.collation;
144
153
  if (cmd.readConcern) findCmd.readConcern = cmd.readConcern;
145
154
 
146
- // If we have explain, we need to rewrite the find command
147
- // to wrap it in the explain command
148
- if (cmd.explain) {
149
- findCmd = {
150
- explain: findCmd
151
- };
152
- }
153
-
154
155
  return findCmd;
155
156
  }
156
157
 
@@ -188,7 +189,7 @@ function prepareLegacyFindQuery(server, ns, cmd, cursorState, options) {
188
189
  if (typeof cmd.showDiskLoc !== 'undefined') findCmd['$showDiskLoc'] = cmd.showDiskLoc;
189
190
  if (cmd.comment) findCmd['$comment'] = cmd.comment;
190
191
  if (cmd.maxTimeMS) findCmd['$maxTimeMS'] = cmd.maxTimeMS;
191
- if (cmd.explain) {
192
+ if (options.explain !== undefined) {
192
193
  // nToReturn must be 0 (match all) or negative (match N and close cursor)
193
194
  // nToReturn > 0 will give explain results equivalent to limit(0)
194
195
  numberToReturn = -Math.abs(cmd.limit || 0);
@@ -3,6 +3,8 @@
3
3
  const MongoError = require('../error').MongoError;
4
4
  const collectionNamespace = require('./shared').collectionNamespace;
5
5
  const command = require('./command');
6
+ const decorateWithExplain = require('../../utils').decorateWithExplain;
7
+ const Explain = require('../../explain').Explain;
6
8
 
7
9
  function writeCommand(server, type, opsField, ns, ops, options, callback) {
8
10
  if (ops.length === 0) throw new MongoError(`${type} must contain at least one document`);
@@ -15,7 +17,7 @@ function writeCommand(server, type, opsField, ns, ops, options, callback) {
15
17
  const ordered = typeof options.ordered === 'boolean' ? options.ordered : true;
16
18
  const writeConcern = options.writeConcern;
17
19
 
18
- const writeCommand = {};
20
+ let writeCommand = {};
19
21
  writeCommand[type] = collectionNamespace(ns);
20
22
  writeCommand[opsField] = ops;
21
23
  writeCommand.ordered = ordered;
@@ -36,6 +38,13 @@ function writeCommand(server, type, opsField, ns, ops, options, callback) {
36
38
  writeCommand.bypassDocumentValidation = options.bypassDocumentValidation;
37
39
  }
38
40
 
41
+ // If a command is to be explained, we need to reformat the command after
42
+ // the other command properties are specified.
43
+ const explain = Explain.fromOptions(options);
44
+ if (explain) {
45
+ writeCommand = decorateWithExplain(writeCommand, explain);
46
+ }
47
+
39
48
  const commandOptions = Object.assign(
40
49
  {
41
50
  checkKeys: type === 'insert',
package/lib/cursor.js CHANGED
@@ -12,6 +12,8 @@ const Map = require('./core').BSON.Map;
12
12
  const maybePromise = require('./utils').maybePromise;
13
13
  const executeOperation = require('./operations/execute_operation');
14
14
  const formattedOrderClause = require('./utils').formattedOrderClause;
15
+ const Explain = require('./explain').Explain;
16
+ const Aspect = require('./operations/operation').Aspect;
15
17
 
16
18
  const each = require('./operations/cursor_ops').each;
17
19
  const CountOperation = require('./operations/count');
@@ -999,25 +1001,25 @@ class Cursor extends CoreCursor {
999
1001
 
1000
1002
  /**
1001
1003
  * Execute the explain for the cursor
1004
+ *
1005
+ * For backwards compatibility, a verbosity of true is interpreted as "allPlansExecution"
1006
+ * and false as "queryPlanner". Prior to server version 3.6, aggregate()
1007
+ * ignores the verbosity parameter and executes in "queryPlanner".
1008
+ *
1002
1009
  * @method
1010
+ * @param {'queryPlanner'|'queryPlannerExtended'|'executionStats'|'allPlansExecution'|boolean} [verbosity=true] - An optional mode in which to run the explain.
1003
1011
  * @param {Cursor~resultCallback} [callback] The result callback.
1004
1012
  * @return {Promise} returns Promise if no callback passed
1005
1013
  */
1006
- explain(callback) {
1007
- // NOTE: the next line includes a special case for operations which do not
1008
- // subclass `CommandOperationV2`. To be removed asap.
1009
- if (this.operation && this.operation.cmd == null) {
1010
- this.operation.options.explain = true;
1011
- this.operation.fullResponse = false;
1012
- return executeOperation(this.topology, this.operation, callback);
1013
- }
1014
-
1015
- this.cmd.explain = true;
1014
+ explain(verbosity, callback) {
1015
+ if (typeof verbosity === 'function') (callback = verbosity), (verbosity = true);
1016
+ if (verbosity === undefined) verbosity = true;
1016
1017
 
1017
- // Do we have a readConcern
1018
- if (this.cmd.readConcern) {
1019
- delete this.cmd['readConcern'];
1018
+ if (!this.operation || !this.operation.hasAspect(Aspect.EXPLAINABLE)) {
1019
+ throw new MongoError('This command cannot be explained');
1020
1020
  }
1021
+ this.operation.explain = new Explain(verbosity);
1022
+
1021
1023
  return maybePromise(this, callback, cb => {
1022
1024
  CoreCursor.prototype._next.apply(this, [cb]);
1023
1025
  });
package/lib/db.js CHANGED
@@ -72,6 +72,7 @@ const legalOptionNames = [
72
72
  'wtimeout',
73
73
  'fsync',
74
74
  'j',
75
+ 'writeConcern',
75
76
  'readPreference',
76
77
  'readPreferenceTags',
77
78
  'native_parser',
@@ -105,9 +106,10 @@ const legalOptionNames = [
105
106
  * @param {(Server|ReplSet|Mongos)} topology The server topology for the database.
106
107
  * @param {object} [options] Optional settings.
107
108
  * @param {string} [options.authSource] If the database authentication is dependent on another databaseName.
108
- * @param {(number|string)} [options.w] The write concern.
109
- * @param {number} [options.wtimeout] The write concern timeout.
110
- * @param {boolean} [options.j=false] Specify a journal write concern.
109
+ * @param {(number|string)} [options.w] **Deprecated** The write concern. Use writeConcern instead.
110
+ * @param {number} [options.wtimeout] **Deprecated** The write concern timeout. Use writeConcern instead.
111
+ * @param {boolean} [options.j=false] **Deprecated** Specify a journal write concern. Use writeConcern instead.
112
+ * @param {object|WriteConcern} [options.writeConcern] Specify write concern settings.
111
113
  * @param {boolean} [options.forceServerObjectId=false] Force server to assign _id values instead of driver.
112
114
  * @param {boolean} [options.serializeFunctions=false] Serialize functions on any object.
113
115
  * @param {Boolean} [options.ignoreUndefined=false] Specify if the BSON serializer should ignore undefined fields.
@@ -211,6 +213,14 @@ function Db(databaseName, topology, options) {
211
213
 
212
214
  inherits(Db, EventEmitter);
213
215
 
216
+ Db.prototype.on = deprecate(function() {
217
+ return Db.super_.prototype.on.apply(this, arguments);
218
+ }, 'Listening to events on the Db class has been deprecated and will be removed in the next major version.');
219
+
220
+ Db.prototype.once = deprecate(function() {
221
+ return Db.super_.prototype.once.apply(this, arguments);
222
+ }, 'Listening to events on the Db class has been deprecated and will be removed in the next major version.');
223
+
214
224
  // Topology
215
225
  Object.defineProperty(Db.prototype, 'topology', {
216
226
  enumerable: true,
@@ -304,7 +314,7 @@ Db.prototype.command = function(command, options, callback) {
304
314
  * @param {number} [options.batchSize=1000] The number of documents to return per batch. See {@link https://docs.mongodb.com/manual/reference/command/aggregate|aggregation documentation}.
305
315
  * @param {object} [options.cursor] Return the query as cursor, on 2.6 > it returns as a real cursor on pre 2.6 it returns as an emulated cursor.
306
316
  * @param {number} [options.cursor.batchSize=1000] Deprecated. Use `options.batchSize`
307
- * @param {boolean} [options.explain=false] Explain returns the aggregation execution plan (requires mongodb 2.6 >).
317
+ * @param {'queryPlanner'|'queryPlannerExtended'|'executionStats'|'allPlansExecution'|boolean} [options.explain] The verbosity mode for the explain output.
308
318
  * @param {boolean} [options.allowDiskUse=false] allowDiskUse lets the server know if it can use disk to store temporary results for the aggregation (requires mongodb 2.6 >).
309
319
  * @param {number} [options.maxTimeMS] maxTimeMS specifies a cumulative time limit in milliseconds for processing operations on the cursor. MongoDB interrupts the operation at the earliest following interrupt point.
310
320
  * @param {number} [options.maxAwaitTimeMS] The maximum amount of time for the server to wait on new documents to satisfy a tailable cursor query.
@@ -391,9 +401,10 @@ const collectionKeys = [
391
401
  * @method
392
402
  * @param {string} name the collection name we wish to access.
393
403
  * @param {object} [options] Optional settings.
394
- * @param {(number|string)} [options.w] The write concern.
395
- * @param {number} [options.wtimeout] The write concern timeout.
396
- * @param {boolean} [options.j=false] Specify a journal write concern.
404
+ * @param {(number|string)} [options.w] **Deprecated** The write concern. Use writeConcern instead.
405
+ * @param {number} [options.wtimeout] **Deprecated** The write concern timeout. Use writeConcern instead.
406
+ * @param {boolean} [options.j=false] **Deprecated** Specify a journal write concern. Use writeConcern instead.
407
+ * @param {object|WriteConcern} [options.writeConcern] Specify write concern settings.
397
408
  * @param {boolean} [options.raw=false] Return document results as raw BSON buffers.
398
409
  * @param {object} [options.pkFactory] A primary key factory object for generation of custom _id keys.
399
410
  * @param {(ReadPreference|string)} [options.readPreference] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
@@ -485,9 +496,10 @@ Db.prototype.collection = function(name, options, callback) {
485
496
  * @method
486
497
  * @param {string} name the collection name we wish to access.
487
498
  * @param {object} [options] Optional settings.
488
- * @param {(number|string)} [options.w] The write concern.
489
- * @param {number} [options.wtimeout] The write concern timeout.
490
- * @param {boolean} [options.j=false] Specify a journal write concern.
499
+ * @param {(number|string)} [options.w] **Deprecated** The write concern. Use writeConcern instead.
500
+ * @param {number} [options.wtimeout] **Deprecated** The write concern timeout. Use writeConcern instead.
501
+ * @param {boolean} [options.j=false] **Deprecated** Specify a journal write concern. Use writeConcern instead.
502
+ * @param {object|WriteConcern} [options.writeConcern] Specify write concern settings.
491
503
  * @param {boolean} [options.raw=false] Return document results as raw BSON buffers.
492
504
  * @param {object} [options.pkFactory] A primary key factory object for generation of custom _id keys.
493
505
  * @param {(ReadPreference|string)} [options.readPreference] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
@@ -513,7 +525,7 @@ Db.prototype.collection = function(name, options, callback) {
513
525
  Db.prototype.createCollection = deprecateOptions(
514
526
  {
515
527
  name: 'Db.createCollection',
516
- deprecatedOptions: ['autoIndexId', 'strict'],
528
+ deprecatedOptions: ['autoIndexId', 'strict', 'w', 'wtimeout', 'j'],
517
529
  optionsIndex: 1
518
530
  },
519
531
  function(name, options, callback) {
@@ -643,10 +655,10 @@ Db.prototype.renameCollection = function(fromCollection, toCollection, options,
643
655
  * @method
644
656
  * @param {string} name Name of collection to drop
645
657
  * @param {Object} [options] Optional settings
646
- * @param {WriteConcern} [options.writeConcern] A full WriteConcern object
647
- * @param {(number|string)} [options.w] The write concern
648
- * @param {number} [options.wtimeout] The write concern timeout
649
- * @param {boolean} [options.j] The journal write concern
658
+ * @param {(number|string)} [options.w] **Deprecated** The write concern. Use writeConcern instead.
659
+ * @param {number} [options.wtimeout] **Deprecated** The write concern timeout. Use writeConcern instead.
660
+ * @param {boolean} [options.j=false] **Deprecated** Specify a journal write concern. Use writeConcern instead.
661
+ * @param {object|WriteConcern} [options.writeConcern] Specify write concern settings.
650
662
  * @param {ClientSession} [options.session] optional session to use for this operation
651
663
  * @param {Db~resultCallback} [callback] The results callback
652
664
  * @return {Promise} returns Promise if no callback passed
@@ -726,9 +738,10 @@ Db.prototype.executeDbAdminCommand = function(selector, options, callback) {
726
738
  * @param {string} name Name of the collection to create the index on.
727
739
  * @param {(string|object)} fieldOrSpec Defines the index.
728
740
  * @param {object} [options] Optional settings.
729
- * @param {(number|string)} [options.w] The write concern.
730
- * @param {number} [options.wtimeout] The write concern timeout.
731
- * @param {boolean} [options.j=false] Specify a journal write concern.
741
+ * @param {(number|string)} [options.w] **Deprecated** The write concern. Use writeConcern instead.
742
+ * @param {number} [options.wtimeout] **Deprecated** The write concern timeout. Use writeConcern instead.
743
+ * @param {boolean} [options.j=false] **Deprecated** Specify a journal write concern. Use writeConcern instead.
744
+ * @param {object|WriteConcern} [options.writeConcern] Specify write concern settings.
732
745
  * @param {boolean} [options.unique=false] Creates an unique index.
733
746
  * @param {boolean} [options.sparse=false] Creates a sparse index.
734
747
  * @param {boolean} [options.background=false] Creates the index in the background, yielding whenever possible.
@@ -760,9 +773,10 @@ Db.prototype.createIndex = function(name, fieldOrSpec, options, callback) {
760
773
  * @param {string} name The index name
761
774
  * @param {(string|object)} fieldOrSpec Defines the index.
762
775
  * @param {object} [options] Optional settings.
763
- * @param {(number|string)} [options.w] The write concern.
764
- * @param {number} [options.wtimeout] The write concern timeout.
765
- * @param {boolean} [options.j=false] Specify a journal write concern.
776
+ * @param {(number|string)} [options.w] **Deprecated** The write concern. Use writeConcern instead.
777
+ * @param {number} [options.wtimeout] **Deprecated** The write concern timeout. Use writeConcern instead.
778
+ * @param {boolean} [options.j=false] **Deprecated** Specify a journal write concern. Use writeConcern instead.
779
+ * @param {object|WriteConcern} [options.writeConcern] Specify write concern settings.
766
780
  * @param {boolean} [options.unique=false] Creates an unique index.
767
781
  * @param {boolean} [options.sparse=false] Creates a sparse index.
768
782
  * @param {boolean} [options.background=false] Creates the index in the background, yielding whenever possible.
@@ -800,9 +814,10 @@ Db.prototype.addChild = function(db) {
800
814
  * @param {string} username The username.
801
815
  * @param {string} password The password.
802
816
  * @param {object} [options] Optional settings.
803
- * @param {(number|string)} [options.w] The write concern.
804
- * @param {number} [options.wtimeout] The write concern timeout.
805
- * @param {boolean} [options.j=false] Specify a journal write concern.
817
+ * @param {(number|string)} [options.w] **Deprecated** The write concern. Use writeConcern instead.
818
+ * @param {number} [options.wtimeout] **Deprecated** The write concern timeout. Use writeConcern instead.
819
+ * @param {boolean} [options.j=false] **Deprecated** Specify a journal write concern. Use writeConcern instead.
820
+ * @param {object|WriteConcern} [options.writeConcern] Specify write concern settings.
806
821
  * @param {object} [options.customData] Custom data associated with the user (only Mongodb 2.6 or higher)
807
822
  * @param {object[]} [options.roles] Roles associated with the created user (only Mongodb 2.6 or higher)
808
823
  * @param {ClientSession} [options.session] optional session to use for this operation
@@ -829,9 +844,10 @@ Db.prototype.addUser = function(username, password, options, callback) {
829
844
  * @method
830
845
  * @param {string} username The username.
831
846
  * @param {object} [options] Optional settings.
832
- * @param {(number|string)} [options.w] The write concern.
833
- * @param {number} [options.wtimeout] The write concern timeout.
834
- * @param {boolean} [options.j=false] Specify a journal write concern.
847
+ * @param {(number|string)} [options.w] **Deprecated** The write concern. Use writeConcern instead.
848
+ * @param {number} [options.wtimeout] **Deprecated** The write concern timeout. Use writeConcern instead.
849
+ * @param {boolean} [options.j=false] **Deprecated** Specify a journal write concern. Use writeConcern instead.
850
+ * @param {object|WriteConcern} [options.writeConcern] Specify write concern settings.
835
851
  * @param {ClientSession} [options.session] optional session to use for this operation
836
852
  * @param {Db~resultCallback} [callback] The command result callback
837
853
  * @return {Promise} returns Promise if no callback passed
package/lib/explain.js ADDED
@@ -0,0 +1,55 @@
1
+ 'use strict';
2
+
3
+ const MongoError = require('./core/error').MongoError;
4
+
5
+ const ExplainVerbosity = {
6
+ queryPlanner: 'queryPlanner',
7
+ queryPlannerExtended: 'queryPlannerExtended',
8
+ executionStats: 'executionStats',
9
+ allPlansExecution: 'allPlansExecution'
10
+ };
11
+
12
+ /**
13
+ * @class
14
+ * @property {'queryPlanner'|'queryPlannerExtended'|'executionStats'|'allPlansExecution'} verbosity The verbosity mode for the explain output.
15
+ */
16
+ class Explain {
17
+ /**
18
+ * Constructs an Explain from the explain verbosity.
19
+ *
20
+ * For backwards compatibility, true is interpreted as "allPlansExecution"
21
+ * and false as "queryPlanner". Prior to server version 3.6, aggregate()
22
+ * ignores the verbosity parameter and executes in "queryPlanner".
23
+ *
24
+ * @param {'queryPlanner'|'queryPlannerExtended'|'executionStats'|'allPlansExecution'|boolean} [verbosity] The verbosity mode for the explain output.
25
+ */
26
+ constructor(verbosity) {
27
+ if (typeof verbosity === 'boolean') {
28
+ this.verbosity = verbosity ? 'allPlansExecution' : 'queryPlanner';
29
+ } else {
30
+ this.verbosity = verbosity;
31
+ }
32
+ }
33
+
34
+ /**
35
+ * Construct an Explain given an options object.
36
+ *
37
+ * @param {object} [options] The options object from which to extract the explain.
38
+ * @param {'queryPlanner'|'queryPlannerExtended'|'executionStats'|'allPlansExecution'|boolean} [options.explain] The verbosity mode for the explain output
39
+ * @return {Explain}
40
+ */
41
+ static fromOptions(options) {
42
+ if (options == null || options.explain === undefined) {
43
+ return;
44
+ }
45
+
46
+ const explain = options.explain;
47
+ if (typeof explain === 'boolean' || explain in ExplainVerbosity) {
48
+ return new Explain(options.explain);
49
+ }
50
+
51
+ throw new MongoError(`explain must be one of ${Object.keys(ExplainVerbosity)} or a boolean`);
52
+ }
53
+ }
54
+
55
+ module.exports = { Explain };
@@ -73,10 +73,11 @@ const deprecationFn = deprecate(() => {},
73
73
  * @param {string} [filename] optional filename for this file, no unique constrain on the field
74
74
  * @param {string} mode set the mode for this file.
75
75
  * @param {object} [options] Optional settings.
76
- * @param {(number|string)} [options.w] The write concern.
77
- * @param {number} [options.wtimeout] The write concern timeout.
78
- * @param {boolean} [options.j=false] Specify a journal write concern.
79
- * @param {boolean} [options.fsync=false] Specify a file sync write concern.
76
+ * @param {(number|string)} [options.w] **Deprecated** The write concern. Use writeConcern instead.
77
+ * @param {number} [options.wtimeout] **Deprecated** The write concern timeout. Use writeConcern instead.
78
+ * @param {boolean} [options.j=false] **Deprecated** Specify a journal write concern. Use writeConcern instead.
79
+ * @param {boolean} [options.fsync=false] **Deprecated** Specify a file sync write concern. Use writeConcern instead.
80
+ * @param {object|WriteConcern} [options.writeConcern] Specify write concern settings.
80
81
  * @param {string} [options.root] Root collection to use. Defaults to **{GridStore.DEFAULT_ROOT_COLLECTION}**.
81
82
  * @param {string} [options.content_type] MIME type of the file. Defaults to **{GridStore.DEFAULT_CONTENT_TYPE}**.
82
83
  * @param {number} [options.chunk_size=261120] Size for the chunk. Defaults to **{Chunk.DEFAULT_CHUNK_SIZE}**.
@@ -1572,12 +1573,13 @@ var _writeNormal = function(self, data, close, options, callback) {
1572
1573
  * @ignore
1573
1574
  */
1574
1575
  var _setWriteConcernHash = function(options) {
1576
+ const baseOptions = Object.assign(options, options.writeConcern);
1575
1577
  var finalOptions = {};
1576
- if (options.w != null) finalOptions.w = options.w;
1577
- if (options.journal === true) finalOptions.j = options.journal;
1578
- if (options.j === true) finalOptions.j = options.j;
1579
- if (options.fsync === true) finalOptions.fsync = options.fsync;
1580
- if (options.wtimeout != null) finalOptions.wtimeout = options.wtimeout;
1578
+ if (baseOptions.w != null) finalOptions.w = baseOptions.w;
1579
+ if (baseOptions.journal === true) finalOptions.j = baseOptions.journal;
1580
+ if (baseOptions.j === true) finalOptions.j = baseOptions.j;
1581
+ if (baseOptions.fsync === true) finalOptions.fsync = baseOptions.fsync;
1582
+ if (baseOptions.wtimeout != null) finalOptions.wtimeout = baseOptions.wtimeout;
1581
1583
  return finalOptions;
1582
1584
  };
1583
1585
 
@@ -1591,6 +1593,7 @@ var _getWriteConcern = function(self, options) {
1591
1593
 
1592
1594
  // Local options verification
1593
1595
  if (
1596
+ options.writeConcern != null ||
1594
1597
  options.w != null ||
1595
1598
  typeof options.j === 'boolean' ||
1596
1599
  typeof options.journal === 'boolean' ||
@@ -1602,6 +1605,7 @@ var _getWriteConcern = function(self, options) {
1602
1605
  } else if (typeof options.safe === 'boolean') {
1603
1606
  finalOptions = { w: options.safe ? 1 : 0 };
1604
1607
  } else if (
1608
+ self.options.writeConcern != null ||
1605
1609
  self.options.w != null ||
1606
1610
  typeof self.options.j === 'boolean' ||
1607
1611
  typeof self.options.journal === 'boolean' ||
@@ -22,9 +22,10 @@ module.exports = GridFSBucketWriteStream;
22
22
  * @param {object} [options] Optional settings.
23
23
  * @param {string|number|object} [options.id] Custom file id for the GridFS file.
24
24
  * @param {number} [options.chunkSizeBytes] The chunk size to use, in bytes
25
- * @param {number} [options.w] The write concern
26
- * @param {number} [options.wtimeout] The write concern timeout
27
- * @param {number} [options.j] The journal write concern
25
+ * @param {(number|string)} [options.w] **Deprecated** The write concern. Use writeConcern instead.
26
+ * @param {number} [options.wtimeout] **Deprecated** The write concern timeout. Use writeConcern instead.
27
+ * @param {boolean} [options.j=false] **Deprecated** Specify a journal write concern. Use writeConcern instead.
28
+ * @param {object|WriteConcern} [options.writeConcern] Specify write concern settings.
28
29
  * @param {boolean} [options.disableMD5=false] If true, disables adding an md5 field to file data
29
30
  * @fires GridFSBucketWriteStream#error
30
31
  * @fires GridFSBucketWriteStream#finish
@@ -32,6 +33,7 @@ module.exports = GridFSBucketWriteStream;
32
33
 
33
34
  function GridFSBucketWriteStream(bucket, filename, options) {
34
35
  options = options || {};
36
+ stream.Writable.call(this, options);
35
37
  this.bucket = bucket;
36
38
  this.chunks = bucket.s._chunksCollection;
37
39
  this.filename = filename;