mongo_client.js 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  1. 'use strict';
  2. const ChangeStream = require('./change_stream');
  3. const Db = require('./db');
  4. const EventEmitter = require('events').EventEmitter;
  5. const inherits = require('util').inherits;
  6. const MongoError = require('./core').MongoError;
  7. const deprecate = require('util').deprecate;
  8. const WriteConcern = require('./write_concern');
  9. const MongoDBNamespace = require('./utils').MongoDBNamespace;
  10. const ReadPreference = require('./core/topologies/read_preference');
  11. const maybePromise = require('./utils').maybePromise;
  12. const NativeTopology = require('./topologies/native_topology');
  13. const connect = require('./operations/connect').connect;
  14. const validOptions = require('./operations/connect').validOptions;
  15. /**
  16. * @fileOverview The **MongoClient** class is a class that allows for making Connections to MongoDB.
  17. *
  18. * @example
  19. * // Connect using a MongoClient instance
  20. * const MongoClient = require('mongodb').MongoClient;
  21. * const test = require('assert');
  22. * // Connection url
  23. * const url = 'mongodb://localhost:27017';
  24. * // Database Name
  25. * const dbName = 'test';
  26. * // Connect using MongoClient
  27. * const mongoClient = new MongoClient(url);
  28. * mongoClient.connect(function(err, client) {
  29. * const db = client.db(dbName);
  30. * client.close();
  31. * });
  32. *
  33. * @example
  34. * // Connect using the MongoClient.connect static method
  35. * const MongoClient = require('mongodb').MongoClient;
  36. * const test = require('assert');
  37. * // Connection url
  38. * const url = 'mongodb://localhost:27017';
  39. * // Database Name
  40. * const dbName = 'test';
  41. * // Connect using MongoClient
  42. * MongoClient.connect(url, function(err, client) {
  43. * const db = client.db(dbName);
  44. * client.close();
  45. * });
  46. */
  47. /**
  48. * A string specifying the level of a ReadConcern
  49. * @typedef {'local'|'available'|'majority'|'linearizable'|'snapshot'} ReadConcernLevel
  50. * @see https://docs.mongodb.com/manual/reference/read-concern/index.html#read-concern-levels
  51. */
  52. /**
  53. * Configuration options for drivers wrapping the node driver.
  54. *
  55. * @typedef {Object} DriverInfoOptions
  56. * @property {string} [name] The name of the driver
  57. * @property {string} [version] The version of the driver
  58. * @property {string} [platform] Optional platform information
  59. */
  60. /**
  61. * Configuration options for drivers wrapping the node driver.
  62. *
  63. * @typedef {Object} DriverInfoOptions
  64. * @property {string} [name] The name of the driver
  65. * @property {string} [version] The version of the driver
  66. * @property {string} [platform] Optional platform information
  67. */
  68. /**
  69. * Creates a new MongoClient instance
  70. * @class
  71. * @param {string} url The connection URI string
  72. * @param {object} [options] Optional settings
  73. * @param {number} [options.poolSize=5] The maximum size of the individual server pool
  74. * @param {boolean} [options.ssl=false] Enable SSL connection. *deprecated* use `tls` variants
  75. * @param {boolean} [options.sslValidate=false] Validate mongod server certificate against Certificate Authority
  76. * @param {buffer} [options.sslCA=undefined] SSL Certificate store binary buffer *deprecated* use `tls` variants
  77. * @param {buffer} [options.sslCert=undefined] SSL Certificate binary buffer *deprecated* use `tls` variants
  78. * @param {buffer} [options.sslKey=undefined] SSL Key file binary buffer *deprecated* use `tls` variants
  79. * @param {string} [options.sslPass=undefined] SSL Certificate pass phrase *deprecated* use `tls` variants
  80. * @param {buffer} [options.sslCRL=undefined] SSL Certificate revocation list binary buffer *deprecated* use `tls` variants
  81. * @param {boolean|function} [options.checkServerIdentity=true] Ensure we check server identify during SSL, set to false to disable checking. Only works for Node 0.12.x or higher. You can pass in a boolean or your own checkServerIdentity override function. *deprecated* use `tls` variants
  82. * @param {boolean} [options.tls=false] Enable TLS connections
  83. * @param {boolean} [options.tlsInsecure=false] Relax TLS constraints, disabling validation
  84. * @param {string} [options.tlsCAFile] A path to file with either a single or bundle of certificate authorities to be considered trusted when making a TLS connection
  85. * @param {string} [options.tlsCertificateKeyFile] A path to the client certificate file or the client private key file; in the case that they both are needed, the files should be concatenated
  86. * @param {string} [options.tlsCertificateKeyFilePassword] The password to decrypt the client private key to be used for TLS connections
  87. * @param {boolean} [options.tlsAllowInvalidCertificates] Specifies whether or not the driver should error when the server’s TLS certificate is invalid
  88. * @param {boolean} [options.tlsAllowInvalidHostnames] Specifies whether or not the driver should error when there is a mismatch between the server’s hostname and the hostname specified by the TLS certificate
  89. * @param {boolean} [options.autoReconnect=true] Enable autoReconnect for single server instances
  90. * @param {boolean} [options.noDelay=true] TCP Connection no delay
  91. * @param {boolean} [options.keepAlive=true] TCP Connection keep alive enabled
  92. * @param {number} [options.keepAliveInitialDelay=30000] The number of milliseconds to wait before initiating keepAlive on the TCP socket
  93. * @param {number} [options.connectTimeoutMS=10000] How long to wait for a connection to be established before timing out
  94. * @param {number} [options.socketTimeoutMS=360000] How long a send or receive on a socket can take before timing out
  95. * @param {number} [options.family] Version of IP stack. Can be 4, 6 or null (default).
  96. * If null, will attempt to connect with IPv6, and will fall back to IPv4 on failure
  97. * @param {number} [options.reconnectTries=30] Server attempt to reconnect #times
  98. * @param {number} [options.reconnectInterval=1000] Server will wait # milliseconds between retries
  99. * @param {boolean} [options.ha=true] Control if high availability monitoring runs for Replicaset or Mongos proxies
  100. * @param {number} [options.haInterval=10000] The High availability period for replicaset inquiry
  101. * @param {string} [options.replicaSet=undefined] The Replicaset set name
  102. * @param {number} [options.secondaryAcceptableLatencyMS=15] Cutoff latency point in MS for Replicaset member selection
  103. * @param {number} [options.acceptableLatencyMS=15] Cutoff latency point in MS for Mongos proxies selection
  104. * @param {boolean} [options.connectWithNoPrimary=false] Sets if the driver should connect even if no primary is available
  105. * @param {string} [options.authSource=undefined] Define the database to authenticate against
  106. * @param {(number|string)} [options.w] The write concern
  107. * @param {number} [options.wtimeout] The write concern timeout
  108. * @param {boolean} [options.j=false] Specify a journal write concern
  109. * @param {boolean} [options.forceServerObjectId=false] Force server to assign _id values instead of driver
  110. * @param {boolean} [options.serializeFunctions=false] Serialize functions on any object
  111. * @param {Boolean} [options.ignoreUndefined=false] Specify if the BSON serializer should ignore undefined fields
  112. * @param {boolean} [options.raw=false] Return document results as raw BSON buffers
  113. * @param {number} [options.bufferMaxEntries=-1] Sets a cap on how many operations the driver will buffer up before giving up on getting a working connection, default is -1 which is unlimited
  114. * @param {(ReadPreference|string)} [options.readPreference] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST)
  115. * @param {object} [options.pkFactory] A primary key factory object for generation of custom _id keys
  116. * @param {object} [options.promiseLibrary] A Promise library class the application wishes to use such as Bluebird, must be ES6 compatible
  117. * @param {object} [options.readConcern] Specify a read concern for the collection (only MongoDB 3.2 or higher supported)
  118. * @param {ReadConcernLevel} [options.readConcern.level='local'] Specify a read concern level for the collection operations (only MongoDB 3.2 or higher supported)
  119. * @param {number} [options.maxStalenessSeconds=undefined] The max staleness to secondary reads (values under 10 seconds cannot be guaranteed)
  120. * @param {string} [options.loggerLevel=undefined] The logging level (error/warn/info/debug)
  121. * @param {object} [options.logger=undefined] Custom logger object
  122. * @param {boolean} [options.promoteValues=true] Promotes BSON values to native types where possible, set to false to only receive wrapper types
  123. * @param {boolean} [options.promoteBuffers=false] Promotes Binary BSON values to native Node Buffers
  124. * @param {boolean} [options.promoteLongs=true] Promotes long values to number if they fit inside the 53 bits resolution
  125. * @param {boolean} [options.domainsEnabled=false] Enable the wrapping of the callback in the current domain, disabled by default to avoid perf hit
  126. * @param {object} [options.validateOptions=false] Validate MongoClient passed in options for correctness
  127. * @param {string} [options.appname=undefined] The name of the application that created this MongoClient instance. MongoDB 3.4 and newer will print this value in the server log upon establishing each connection. It is also recorded in the slow query log and profile collections
  128. * @param {string} [options.auth.user=undefined] The username for auth
  129. * @param {string} [options.auth.password=undefined] The password for auth
  130. * @param {string} [options.authMechanism=undefined] Mechanism for authentication: MDEFAULT, GSSAPI, PLAIN, MONGODB-X509, or SCRAM-SHA-1
  131. * @param {object} [options.compression] Type of compression to use: snappy or zlib
  132. * @param {boolean} [options.fsync=false] Specify a file sync write concern
  133. * @param {array} [options.readPreferenceTags] Read preference tags
  134. * @param {number} [options.numberOfRetries=5] The number of retries for a tailable cursor
  135. * @param {boolean} [options.auto_reconnect=true] Enable auto reconnecting for single server instances
  136. * @param {boolean} [options.monitorCommands=false] Enable command monitoring for this client
  137. * @param {number} [options.minSize] If present, the connection pool will be initialized with minSize connections, and will never dip below minSize connections
  138. * @param {boolean} [options.useNewUrlParser=true] Determines whether or not to use the new url parser. Enables the new, spec-compliant, url parser shipped in the core driver. This url parser fixes a number of problems with the original parser, and aims to outright replace that parser in the near future. Defaults to true, and must be explicitly set to false to use the legacy url parser.
  139. * @param {boolean} [options.useUnifiedTopology] Enables the new unified topology layer
  140. * @param {Number} [options.localThresholdMS=15] **Only applies to the unified topology** The size of the latency window for selecting among multiple suitable servers
  141. * @param {Number} [options.serverSelectionTimeoutMS=30000] **Only applies to the unified topology** How long to block for server selection before throwing an error
  142. * @param {Number} [options.heartbeatFrequencyMS=10000] **Only applies to the unified topology** The frequency with which topology updates are scheduled
  143. * @param {AutoEncrypter~AutoEncryptionOptions} [options.autoEncryption] Optionally enable client side auto encryption
  144. * @param {DriverInfoOptions} [options.driverInfo] Allows a wrapping driver to amend the client metadata generated by the driver to include information about the wrapping driver
  145. * @param {MongoClient~connectCallback} [callback] The command result callback
  146. * @return {MongoClient} a MongoClient instance
  147. */
  148. function MongoClient(url, options) {
  149. if (!(this instanceof MongoClient)) return new MongoClient(url, options);
  150. // Set up event emitter
  151. EventEmitter.call(this);
  152. // The internal state
  153. this.s = {
  154. url: url,
  155. options: options || {},
  156. promiseLibrary: (options && options.promiseLibrary) || Promise,
  157. dbCache: new Map(),
  158. sessions: new Set(),
  159. writeConcern: WriteConcern.fromOptions(options),
  160. namespace: new MongoDBNamespace('admin')
  161. };
  162. }
  163. /**
  164. * @ignore
  165. */
  166. inherits(MongoClient, EventEmitter);
  167. Object.defineProperty(MongoClient.prototype, 'writeConcern', {
  168. enumerable: true,
  169. get: function() {
  170. return this.s.writeConcern;
  171. }
  172. });
  173. Object.defineProperty(MongoClient.prototype, 'readPreference', {
  174. enumerable: true,
  175. get: function() {
  176. return ReadPreference.primary;
  177. }
  178. });
  179. /**
  180. * The callback format for results
  181. * @callback MongoClient~connectCallback
  182. * @param {MongoError} error An error instance representing the error during the execution.
  183. * @param {MongoClient} client The connected client.
  184. */
  185. /**
  186. * Connect to MongoDB using a url as documented at
  187. *
  188. * docs.mongodb.org/manual/reference/connection-string/
  189. *
  190. * Note that for replicasets the replicaSet query parameter is required in the 2.0 driver
  191. *
  192. * @method
  193. * @param {MongoClient~connectCallback} [callback] The command result callback
  194. * @return {Promise<MongoClient>} returns Promise if no callback passed
  195. */
  196. MongoClient.prototype.connect = function(callback) {
  197. if (typeof callback === 'string') {
  198. throw new TypeError('`connect` only accepts a callback');
  199. }
  200. const client = this;
  201. return maybePromise(this, callback, cb => {
  202. const err = validOptions(client.s.options);
  203. if (err) return cb(err);
  204. connect(client, client.s.url, client.s.options, err => {
  205. if (err) return cb(err);
  206. cb(null, client);
  207. });
  208. });
  209. };
  210. MongoClient.prototype.logout = deprecate(function(options, callback) {
  211. if (typeof options === 'function') (callback = options), (options = {});
  212. if (typeof callback === 'function') callback(null, true);
  213. }, 'Multiple authentication is prohibited on a connected client, please only authenticate once per MongoClient');
  214. /**
  215. * Close the db and its underlying connections
  216. * @method
  217. * @param {boolean} [force=false] Force close, emitting no events
  218. * @param {Db~noResultCallback} [callback] The result callback
  219. * @return {Promise} returns Promise if no callback passed
  220. */
  221. MongoClient.prototype.close = function(force, callback) {
  222. if (typeof force === 'function') {
  223. callback = force;
  224. force = false;
  225. }
  226. const client = this;
  227. return maybePromise(this, callback, cb => {
  228. const completeClose = err => {
  229. client.emit('close', client);
  230. if (!(client.topology instanceof NativeTopology)) {
  231. for (const item of client.s.dbCache) {
  232. item[1].emit('close', client);
  233. }
  234. }
  235. client.removeAllListeners('close');
  236. cb(err);
  237. };
  238. if (client.topology == null) {
  239. completeClose();
  240. return;
  241. }
  242. client.topology.close(force, err => {
  243. const autoEncrypter = client.topology.s.options.autoEncrypter;
  244. if (!autoEncrypter) {
  245. completeClose(err);
  246. return;
  247. }
  248. autoEncrypter.teardown(force, err2 => completeClose(err || err2));
  249. });
  250. });
  251. };
  252. /**
  253. * Create a new Db instance sharing the current socket connections. Be aware that the new db instances are
  254. * related in a parent-child relationship to the original instance so that events are correctly emitted on child
  255. * db instances. Child db instances are cached so performing db('db1') twice will return the same instance.
  256. * You can control these behaviors with the options noListener and returnNonCachedInstance.
  257. *
  258. * @method
  259. * @param {string} [dbName] The name of the database we want to use. If not provided, use database name from connection string.
  260. * @param {object} [options] Optional settings.
  261. * @param {boolean} [options.noListener=false] Do not make the db an event listener to the original connection.
  262. * @param {boolean} [options.returnNonCachedInstance=false] Control if you want to return a cached instance or have a new one created
  263. * @return {Db}
  264. */
  265. MongoClient.prototype.db = function(dbName, options) {
  266. options = options || {};
  267. // Default to db from connection string if not provided
  268. if (!dbName) {
  269. dbName = this.s.options.dbName;
  270. }
  271. // Copy the options and add out internal override of the not shared flag
  272. const finalOptions = Object.assign({}, this.s.options, options);
  273. // Do we have the db in the cache already
  274. if (this.s.dbCache.has(dbName) && finalOptions.returnNonCachedInstance !== true) {
  275. return this.s.dbCache.get(dbName);
  276. }
  277. // Add promiseLibrary
  278. finalOptions.promiseLibrary = this.s.promiseLibrary;
  279. // If no topology throw an error message
  280. if (!this.topology) {
  281. throw new MongoError('MongoClient must be connected before calling MongoClient.prototype.db');
  282. }
  283. // Return the db object
  284. const db = new Db(dbName, this.topology, finalOptions);
  285. // Add the db to the cache
  286. this.s.dbCache.set(dbName, db);
  287. // Return the database
  288. return db;
  289. };
  290. /**
  291. * Check if MongoClient is connected
  292. *
  293. * @method
  294. * @param {object} [options] Optional settings.
  295. * @param {boolean} [options.noListener=false] Do not make the db an event listener to the original connection.
  296. * @param {boolean} [options.returnNonCachedInstance=false] Control if you want to return a cached instance or have a new one created
  297. * @return {boolean}
  298. */
  299. MongoClient.prototype.isConnected = function(options) {
  300. options = options || {};
  301. if (!this.topology) return false;
  302. return this.topology.isConnected(options);
  303. };
  304. /**
  305. * Connect to MongoDB using a url as documented at
  306. *
  307. * docs.mongodb.org/manual/reference/connection-string/
  308. *
  309. * Note that for replicasets the replicaSet query parameter is required in the 2.0 driver
  310. *
  311. * @method
  312. * @static
  313. * @param {string} url The connection URI string
  314. * @param {object} [options] Optional settings
  315. * @param {number} [options.poolSize=5] The maximum size of the individual server pool
  316. * @param {boolean} [options.ssl=false] Enable SSL connection. *deprecated* use `tls` variants
  317. * @param {boolean} [options.sslValidate=false] Validate mongod server certificate against Certificate Authority
  318. * @param {buffer} [options.sslCA=undefined] SSL Certificate store binary buffer *deprecated* use `tls` variants
  319. * @param {buffer} [options.sslCert=undefined] SSL Certificate binary buffer *deprecated* use `tls` variants
  320. * @param {buffer} [options.sslKey=undefined] SSL Key file binary buffer *deprecated* use `tls` variants
  321. * @param {string} [options.sslPass=undefined] SSL Certificate pass phrase *deprecated* use `tls` variants
  322. * @param {buffer} [options.sslCRL=undefined] SSL Certificate revocation list binary buffer *deprecated* use `tls` variants
  323. * @param {boolean|function} [options.checkServerIdentity=true] Ensure we check server identify during SSL, set to false to disable checking. Only works for Node 0.12.x or higher. You can pass in a boolean or your own checkServerIdentity override function. *deprecated* use `tls` variants
  324. * @param {boolean} [options.tls=false] Enable TLS connections
  325. * @param {boolean} [options.tlsInsecure=false] Relax TLS constraints, disabling validation
  326. * @param {string} [options.tlsCAFile] A path to file with either a single or bundle of certificate authorities to be considered trusted when making a TLS connection
  327. * @param {string} [options.tlsCertificateKeyFile] A path to the client certificate file or the client private key file; in the case that they both are needed, the files should be concatenated
  328. * @param {string} [options.tlsCertificateKeyFilePassword] The password to decrypt the client private key to be used for TLS connections
  329. * @param {boolean} [options.tlsAllowInvalidCertificates] Specifies whether or not the driver should error when the server’s TLS certificate is invalid
  330. * @param {boolean} [options.tlsAllowInvalidHostnames] Specifies whether or not the driver should error when there is a mismatch between the server’s hostname and the hostname specified by the TLS certificate
  331. * @param {boolean} [options.autoReconnect=true] Enable autoReconnect for single server instances
  332. * @param {boolean} [options.noDelay=true] TCP Connection no delay
  333. * @param {boolean} [options.keepAlive=true] TCP Connection keep alive enabled
  334. * @param {number} [options.keepAliveInitialDelay=30000] The number of milliseconds to wait before initiating keepAlive on the TCP socket
  335. * @param {number} [options.connectTimeoutMS=10000] How long to wait for a connection to be established before timing out
  336. * @param {number} [options.socketTimeoutMS=360000] How long a send or receive on a socket can take before timing out
  337. * @param {number} [options.family] Version of IP stack. Can be 4, 6 or null (default).
  338. * If null, will attempt to connect with IPv6, and will fall back to IPv4 on failure
  339. * @param {number} [options.reconnectTries=30] Server attempt to reconnect #times
  340. * @param {number} [options.reconnectInterval=1000] Server will wait # milliseconds between retries
  341. * @param {boolean} [options.ha=true] Control if high availability monitoring runs for Replicaset or Mongos proxies
  342. * @param {number} [options.haInterval=10000] The High availability period for replicaset inquiry
  343. * @param {string} [options.replicaSet=undefined] The Replicaset set name
  344. * @param {number} [options.secondaryAcceptableLatencyMS=15] Cutoff latency point in MS for Replicaset member selection
  345. * @param {number} [options.acceptableLatencyMS=15] Cutoff latency point in MS for Mongos proxies selection
  346. * @param {boolean} [options.connectWithNoPrimary=false] Sets if the driver should connect even if no primary is available
  347. * @param {string} [options.authSource=undefined] Define the database to authenticate against
  348. * @param {(number|string)} [options.w] The write concern
  349. * @param {number} [options.wtimeout] The write concern timeout
  350. * @param {boolean} [options.j=false] Specify a journal write concern
  351. * @param {boolean} [options.forceServerObjectId=false] Force server to assign _id values instead of driver
  352. * @param {boolean} [options.serializeFunctions=false] Serialize functions on any object
  353. * @param {Boolean} [options.ignoreUndefined=false] Specify if the BSON serializer should ignore undefined fields
  354. * @param {boolean} [options.raw=false] Return document results as raw BSON buffers
  355. * @param {number} [options.bufferMaxEntries=-1] Sets a cap on how many operations the driver will buffer up before giving up on getting a working connection, default is -1 which is unlimited
  356. * @param {(ReadPreference|string)} [options.readPreference] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST)
  357. * @param {object} [options.pkFactory] A primary key factory object for generation of custom _id keys
  358. * @param {object} [options.promiseLibrary] A Promise library class the application wishes to use such as Bluebird, must be ES6 compatible
  359. * @param {object} [options.readConcern] Specify a read concern for the collection (only MongoDB 3.2 or higher supported)
  360. * @param {ReadConcernLevel} [options.readConcern.level='local'] Specify a read concern level for the collection operations (only MongoDB 3.2 or higher supported)
  361. * @param {number} [options.maxStalenessSeconds=undefined] The max staleness to secondary reads (values under 10 seconds cannot be guaranteed)
  362. * @param {string} [options.loggerLevel=undefined] The logging level (error/warn/info/debug)
  363. * @param {object} [options.logger=undefined] Custom logger object
  364. * @param {boolean} [options.promoteValues=true] Promotes BSON values to native types where possible, set to false to only receive wrapper types
  365. * @param {boolean} [options.promoteBuffers=false] Promotes Binary BSON values to native Node Buffers
  366. * @param {boolean} [options.promoteLongs=true] Promotes long values to number if they fit inside the 53 bits resolution
  367. * @param {boolean} [options.domainsEnabled=false] Enable the wrapping of the callback in the current domain, disabled by default to avoid perf hit
  368. * @param {object} [options.validateOptions=false] Validate MongoClient passed in options for correctness
  369. * @param {string} [options.appname=undefined] The name of the application that created this MongoClient instance. MongoDB 3.4 and newer will print this value in the server log upon establishing each connection. It is also recorded in the slow query log and profile collections
  370. * @param {string} [options.auth.user=undefined] The username for auth
  371. * @param {string} [options.auth.password=undefined] The password for auth
  372. * @param {string} [options.authMechanism=undefined] Mechanism for authentication: MDEFAULT, GSSAPI, PLAIN, MONGODB-X509, or SCRAM-SHA-1
  373. * @param {object} [options.compression] Type of compression to use: snappy or zlib
  374. * @param {boolean} [options.fsync=false] Specify a file sync write concern
  375. * @param {array} [options.readPreferenceTags] Read preference tags
  376. * @param {number} [options.numberOfRetries=5] The number of retries for a tailable cursor
  377. * @param {boolean} [options.auto_reconnect=true] Enable auto reconnecting for single server instances
  378. * @param {boolean} [options.monitorCommands=false] Enable command monitoring for this client
  379. * @param {number} [options.minSize] If present, the connection pool will be initialized with minSize connections, and will never dip below minSize connections
  380. * @param {boolean} [options.useNewUrlParser=true] Determines whether or not to use the new url parser. Enables the new, spec-compliant, url parser shipped in the core driver. This url parser fixes a number of problems with the original parser, and aims to outright replace that parser in the near future. Defaults to true, and must be explicitly set to false to use the legacy url parser.
  381. * @param {boolean} [options.useUnifiedTopology] Enables the new unified topology layer
  382. * @param {Number} [options.localThresholdMS=15] **Only applies to the unified topology** The size of the latency window for selecting among multiple suitable servers
  383. * @param {Number} [options.serverSelectionTimeoutMS=30000] **Only applies to the unified topology** How long to block for server selection before throwing an error
  384. * @param {Number} [options.heartbeatFrequencyMS=10000] **Only applies to the unified topology** The frequency with which topology updates are scheduled
  385. * @param {AutoEncrypter~AutoEncryptionOptions} [options.autoEncryption] Optionally enable client side auto encryption
  386. * @param {DriverInfoOptions} [options.driverInfo] Allows a wrapping driver to amend the client metadata generated by the driver to include information about the wrapping driver
  387. * @param {MongoClient~connectCallback} [callback] The command result callback
  388. * @return {Promise<MongoClient>} returns Promise if no callback passed
  389. */
  390. MongoClient.connect = function(url, options, callback) {
  391. const args = Array.prototype.slice.call(arguments, 1);
  392. callback = typeof args[args.length - 1] === 'function' ? args.pop() : undefined;
  393. options = args.length ? args.shift() : null;
  394. options = options || {};
  395. // Create client
  396. const mongoClient = new MongoClient(url, options);
  397. // Execute the connect method
  398. return mongoClient.connect(callback);
  399. };
  400. /**
  401. * Starts a new session on the server
  402. *
  403. * @param {SessionOptions} [options] optional settings for a driver session
  404. * @return {ClientSession} the newly established session
  405. */
  406. MongoClient.prototype.startSession = function(options) {
  407. options = Object.assign({ explicit: true }, options);
  408. if (!this.topology) {
  409. throw new MongoError('Must connect to a server before calling this method');
  410. }
  411. if (!this.topology.hasSessionSupport()) {
  412. throw new MongoError('Current topology does not support sessions');
  413. }
  414. return this.topology.startSession(options, this.s.options);
  415. };
  416. /**
  417. * Runs a given operation with an implicitly created session. The lifetime of the session
  418. * will be handled without the need for user interaction.
  419. *
  420. * NOTE: presently the operation MUST return a Promise (either explicit or implicity as an async function)
  421. *
  422. * @param {Object} [options] Optional settings to be appled to implicitly created session
  423. * @param {Function} operation An operation to execute with an implicitly created session. The signature of this MUST be `(session) => {}`
  424. * @return {Promise}
  425. */
  426. MongoClient.prototype.withSession = function(options, operation) {
  427. if (typeof options === 'function') (operation = options), (options = undefined);
  428. const session = this.startSession(options);
  429. let cleanupHandler = (err, result, opts) => {
  430. // prevent multiple calls to cleanupHandler
  431. cleanupHandler = () => {
  432. throw new ReferenceError('cleanupHandler was called too many times');
  433. };
  434. opts = Object.assign({ throw: true }, opts);
  435. session.endSession();
  436. if (err) {
  437. if (opts.throw) throw err;
  438. return Promise.reject(err);
  439. }
  440. };
  441. try {
  442. const result = operation(session);
  443. return Promise.resolve(result)
  444. .then(result => cleanupHandler(null, result))
  445. .catch(err => cleanupHandler(err, null, { throw: true }));
  446. } catch (err) {
  447. return cleanupHandler(err, null, { throw: false });
  448. }
  449. };
  450. /**
  451. * Create a new Change Stream, watching for new changes (insertions, updates, replacements, deletions, and invalidations) in this cluster. Will ignore all changes to system collections, as well as the local, admin,
  452. * and config databases.
  453. * @method
  454. * @since 3.1.0
  455. * @param {Array} [pipeline] An array of {@link https://docs.mongodb.com/manual/reference/operator/aggregation-pipeline/|aggregation pipeline stages} through which to pass change stream documents. This allows for filtering (using $match) and manipulating the change stream documents.
  456. * @param {object} [options] Optional settings
  457. * @param {string} [options.fullDocument='default'] Allowed values: ‘default’, ‘updateLookup’. When set to ‘updateLookup’, the change stream will include both a delta describing the changes to the document, as well as a copy of the entire document that was changed from some time after the change occurred.
  458. * @param {object} [options.resumeAfter] Specifies the logical starting point for the new change stream. This should be the _id field from a previously returned change stream document.
  459. * @param {number} [options.maxAwaitTimeMS] The maximum amount of time for the server to wait on new documents to satisfy a change stream query
  460. * @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}.
  461. * @param {object} [options.collation] Specify collation settings for operation. See {@link https://docs.mongodb.com/manual/reference/command/aggregate|aggregation documentation}.
  462. * @param {ReadPreference} [options.readPreference] The read preference. See {@link https://docs.mongodb.com/manual/reference/read-preference|read preference documentation}.
  463. * @param {Timestamp} [options.startAtOperationTime] receive change events that occur after the specified timestamp
  464. * @param {ClientSession} [options.session] optional session to use for this operation
  465. * @return {ChangeStream} a ChangeStream instance.
  466. */
  467. MongoClient.prototype.watch = function(pipeline, options) {
  468. pipeline = pipeline || [];
  469. options = options || {};
  470. // Allow optionally not specifying a pipeline
  471. if (!Array.isArray(pipeline)) {
  472. options = pipeline;
  473. pipeline = [];
  474. }
  475. return new ChangeStream(this, pipeline, options);
  476. };
  477. /**
  478. * Return the mongo client logger
  479. * @method
  480. * @return {Logger} return the mongo client logger
  481. * @ignore
  482. */
  483. MongoClient.prototype.getLogger = function() {
  484. return this.s.options.logger;
  485. };
  486. module.exports = MongoClient;