db.js 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031
  1. 'use strict';
  2. const EventEmitter = require('events').EventEmitter;
  3. const inherits = require('util').inherits;
  4. const getSingleProperty = require('./utils').getSingleProperty;
  5. const CommandCursor = require('./command_cursor');
  6. const handleCallback = require('./utils').handleCallback;
  7. const filterOptions = require('./utils').filterOptions;
  8. const toError = require('./utils').toError;
  9. const ReadPreference = require('./core').ReadPreference;
  10. const MongoError = require('./core').MongoError;
  11. const ObjectID = require('./core').ObjectID;
  12. const Logger = require('./core').Logger;
  13. const Collection = require('./collection');
  14. const mergeOptionsAndWriteConcern = require('./utils').mergeOptionsAndWriteConcern;
  15. const executeLegacyOperation = require('./utils').executeLegacyOperation;
  16. const resolveReadPreference = require('./utils').resolveReadPreference;
  17. const ChangeStream = require('./change_stream');
  18. const deprecate = require('util').deprecate;
  19. const deprecateOptions = require('./utils').deprecateOptions;
  20. const MongoDBNamespace = require('./utils').MongoDBNamespace;
  21. const CONSTANTS = require('./constants');
  22. const WriteConcern = require('./write_concern');
  23. const ReadConcern = require('./read_concern');
  24. const AggregationCursor = require('./aggregation_cursor');
  25. // Operations
  26. const createListener = require('./operations/db_ops').createListener;
  27. const ensureIndex = require('./operations/db_ops').ensureIndex;
  28. const evaluate = require('./operations/db_ops').evaluate;
  29. const profilingInfo = require('./operations/db_ops').profilingInfo;
  30. const validateDatabaseName = require('./operations/db_ops').validateDatabaseName;
  31. const AggregateOperation = require('./operations/aggregate');
  32. const AddUserOperation = require('./operations/add_user');
  33. const CollectionsOperation = require('./operations/collections');
  34. const CommandOperation = require('./operations/command');
  35. const CreateCollectionOperation = require('./operations/create_collection');
  36. const CreateIndexOperation = require('./operations/create_index');
  37. const DropCollectionOperation = require('./operations/drop').DropCollectionOperation;
  38. const DropDatabaseOperation = require('./operations/drop').DropDatabaseOperation;
  39. const ExecuteDbAdminCommandOperation = require('./operations/execute_db_admin_command');
  40. const IndexInformationOperation = require('./operations/index_information');
  41. const ListCollectionsOperation = require('./operations/list_collections');
  42. const ProfilingLevelOperation = require('./operations/profiling_level');
  43. const RemoveUserOperation = require('./operations/remove_user');
  44. const RenameOperation = require('./operations/rename');
  45. const SetProfilingLevelOperation = require('./operations/set_profiling_level');
  46. const executeOperation = require('./operations/execute_operation');
  47. /**
  48. * @fileOverview The **Db** class is a class that represents a MongoDB Database.
  49. *
  50. * @example
  51. * const MongoClient = require('mongodb').MongoClient;
  52. * // Connection url
  53. * const url = 'mongodb://localhost:27017';
  54. * // Database Name
  55. * const dbName = 'test';
  56. * // Connect using MongoClient
  57. * MongoClient.connect(url, function(err, client) {
  58. * // Select the database by name
  59. * const testDb = client.db(dbName);
  60. * client.close();
  61. * });
  62. */
  63. // Allowed parameters
  64. const legalOptionNames = [
  65. 'w',
  66. 'wtimeout',
  67. 'fsync',
  68. 'j',
  69. 'readPreference',
  70. 'readPreferenceTags',
  71. 'native_parser',
  72. 'forceServerObjectId',
  73. 'pkFactory',
  74. 'serializeFunctions',
  75. 'raw',
  76. 'bufferMaxEntries',
  77. 'authSource',
  78. 'ignoreUndefined',
  79. 'promoteLongs',
  80. 'promiseLibrary',
  81. 'readConcern',
  82. 'retryMiliSeconds',
  83. 'numberOfRetries',
  84. 'parentDb',
  85. 'noListener',
  86. 'loggerLevel',
  87. 'logger',
  88. 'promoteBuffers',
  89. 'promoteLongs',
  90. 'promoteValues',
  91. 'compression',
  92. 'retryWrites'
  93. ];
  94. /**
  95. * Creates a new Db instance
  96. * @class
  97. * @param {string} databaseName The name of the database this instance represents.
  98. * @param {(Server|ReplSet|Mongos)} topology The server topology for the database.
  99. * @param {object} [options] Optional settings.
  100. * @param {string} [options.authSource] If the database authentication is dependent on another databaseName.
  101. * @param {(number|string)} [options.w] The write concern.
  102. * @param {number} [options.wtimeout] The write concern timeout.
  103. * @param {boolean} [options.j=false] Specify a journal write concern.
  104. * @param {boolean} [options.forceServerObjectId=false] Force server to assign _id values instead of driver.
  105. * @param {boolean} [options.serializeFunctions=false] Serialize functions on any object.
  106. * @param {Boolean} [options.ignoreUndefined=false] Specify if the BSON serializer should ignore undefined fields.
  107. * @param {boolean} [options.raw=false] Return document results as raw BSON buffers.
  108. * @param {boolean} [options.promoteLongs=true] Promotes Long values to number if they fit inside the 53 bits resolution.
  109. * @param {boolean} [options.promoteBuffers=false] Promotes Binary BSON values to native Node Buffers.
  110. * @param {boolean} [options.promoteValues=true] Promotes BSON values to native types where possible, set to false to only receive wrapper types.
  111. * @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.
  112. * @param {(ReadPreference|string)} [options.readPreference] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
  113. * @param {object} [options.pkFactory] A primary key factory object for generation of custom _id keys.
  114. * @param {object} [options.promiseLibrary] A Promise library class the application wishes to use such as Bluebird, must be ES6 compatible
  115. * @param {object} [options.readConcern] Specify a read concern for the collection. (only MongoDB 3.2 or higher supported)
  116. * @param {ReadConcernLevel} [options.readConcern.level='local'] Specify a read concern level for the collection operations (only MongoDB 3.2 or higher supported)
  117. * @property {(Server|ReplSet|Mongos)} serverConfig Get the current db topology.
  118. * @property {number} bufferMaxEntries Current bufferMaxEntries value for the database
  119. * @property {string} databaseName The name of the database this instance represents.
  120. * @property {object} options The options associated with the db instance.
  121. * @property {boolean} native_parser The current value of the parameter native_parser.
  122. * @property {boolean} slaveOk The current slaveOk value for the db instance.
  123. * @property {object} writeConcern The current write concern values.
  124. * @property {object} topology Access the topology object (single server, replicaset or mongos).
  125. * @fires Db#close
  126. * @fires Db#reconnect
  127. * @fires Db#error
  128. * @fires Db#timeout
  129. * @fires Db#parseError
  130. * @fires Db#fullsetup
  131. * @return {Db} a Db instance.
  132. */
  133. function Db(databaseName, topology, options) {
  134. options = options || {};
  135. if (!(this instanceof Db)) return new Db(databaseName, topology, options);
  136. EventEmitter.call(this);
  137. // Get the promiseLibrary
  138. const promiseLibrary = options.promiseLibrary || Promise;
  139. // Filter the options
  140. options = filterOptions(options, legalOptionNames);
  141. // Ensure we put the promiseLib in the options
  142. options.promiseLibrary = promiseLibrary;
  143. // Internal state of the db object
  144. this.s = {
  145. // DbCache
  146. dbCache: {},
  147. // Children db's
  148. children: [],
  149. // Topology
  150. topology: topology,
  151. // Options
  152. options: options,
  153. // Logger instance
  154. logger: Logger('Db', options),
  155. // Get the bson parser
  156. bson: topology ? topology.bson : null,
  157. // Unpack read preference
  158. readPreference: ReadPreference.fromOptions(options),
  159. // Set buffermaxEntries
  160. bufferMaxEntries: typeof options.bufferMaxEntries === 'number' ? options.bufferMaxEntries : -1,
  161. // Parent db (if chained)
  162. parentDb: options.parentDb || null,
  163. // Set up the primary key factory or fallback to ObjectID
  164. pkFactory: options.pkFactory || ObjectID,
  165. // Get native parser
  166. nativeParser: options.nativeParser || options.native_parser,
  167. // Promise library
  168. promiseLibrary: promiseLibrary,
  169. // No listener
  170. noListener: typeof options.noListener === 'boolean' ? options.noListener : false,
  171. // ReadConcern
  172. readConcern: ReadConcern.fromOptions(options),
  173. writeConcern: WriteConcern.fromOptions(options),
  174. // Namespace
  175. namespace: new MongoDBNamespace(databaseName)
  176. };
  177. // Ensure we have a valid db name
  178. validateDatabaseName(databaseName);
  179. // Add a read Only property
  180. getSingleProperty(this, 'serverConfig', this.s.topology);
  181. getSingleProperty(this, 'bufferMaxEntries', this.s.bufferMaxEntries);
  182. getSingleProperty(this, 'databaseName', this.s.namespace.db);
  183. // This is a child db, do not register any listeners
  184. if (options.parentDb) return;
  185. if (this.s.noListener) return;
  186. // Add listeners
  187. topology.on('error', createListener(this, 'error', this));
  188. topology.on('timeout', createListener(this, 'timeout', this));
  189. topology.on('close', createListener(this, 'close', this));
  190. topology.on('parseError', createListener(this, 'parseError', this));
  191. topology.once('open', createListener(this, 'open', this));
  192. topology.once('fullsetup', createListener(this, 'fullsetup', this));
  193. topology.once('all', createListener(this, 'all', this));
  194. topology.on('reconnect', createListener(this, 'reconnect', this));
  195. }
  196. inherits(Db, EventEmitter);
  197. // Topology
  198. Object.defineProperty(Db.prototype, 'topology', {
  199. enumerable: true,
  200. get: function() {
  201. return this.s.topology;
  202. }
  203. });
  204. // Options
  205. Object.defineProperty(Db.prototype, 'options', {
  206. enumerable: true,
  207. get: function() {
  208. return this.s.options;
  209. }
  210. });
  211. // slaveOk specified
  212. Object.defineProperty(Db.prototype, 'slaveOk', {
  213. enumerable: true,
  214. get: function() {
  215. if (
  216. this.s.options.readPreference != null &&
  217. (this.s.options.readPreference !== 'primary' ||
  218. this.s.options.readPreference.mode !== 'primary')
  219. ) {
  220. return true;
  221. }
  222. return false;
  223. }
  224. });
  225. Object.defineProperty(Db.prototype, 'readConcern', {
  226. enumerable: true,
  227. get: function() {
  228. return this.s.readConcern;
  229. }
  230. });
  231. Object.defineProperty(Db.prototype, 'readPreference', {
  232. enumerable: true,
  233. get: function() {
  234. if (this.s.readPreference == null) {
  235. // TODO: check client
  236. return ReadPreference.primary;
  237. }
  238. return this.s.readPreference;
  239. }
  240. });
  241. // get the write Concern
  242. Object.defineProperty(Db.prototype, 'writeConcern', {
  243. enumerable: true,
  244. get: function() {
  245. return this.s.writeConcern;
  246. }
  247. });
  248. Object.defineProperty(Db.prototype, 'namespace', {
  249. enumerable: true,
  250. get: function() {
  251. return this.s.namespace.toString();
  252. }
  253. });
  254. /**
  255. * Execute a command
  256. * @method
  257. * @param {object} command The command hash
  258. * @param {object} [options] Optional settings.
  259. * @param {(ReadPreference|string)} [options.readPreference] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
  260. * @param {ClientSession} [options.session] optional session to use for this operation
  261. * @param {Db~resultCallback} [callback] The command result callback
  262. * @return {Promise} returns Promise if no callback passed
  263. */
  264. Db.prototype.command = function(command, options, callback) {
  265. if (typeof options === 'function') (callback = options), (options = {});
  266. options = Object.assign({}, options);
  267. const commandOperation = new CommandOperation(this, options, null, command);
  268. return executeOperation(this.s.topology, commandOperation, callback);
  269. };
  270. /**
  271. * Execute an aggregation framework pipeline against the database, needs MongoDB >= 3.6
  272. * @method
  273. * @param {object} [pipeline=[]] Array containing all the aggregation framework commands for the execution.
  274. * @param {object} [options] Optional settings.
  275. * @param {(ReadPreference|string)} [options.readPreference] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
  276. * @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}.
  277. * @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.
  278. * @param {number} [options.cursor.batchSize=1000] Deprecated. Use `options.batchSize`
  279. * @param {boolean} [options.explain=false] Explain returns the aggregation execution plan (requires mongodb 2.6 >).
  280. * @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 >).
  281. * @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.
  282. * @param {number} [options.maxAwaitTimeMS] The maximum amount of time for the server to wait on new documents to satisfy a tailable cursor query.
  283. * @param {boolean} [options.bypassDocumentValidation=false] Allow driver to bypass schema validation in MongoDB 3.2 or higher.
  284. * @param {boolean} [options.raw=false] Return document results as raw BSON buffers.
  285. * @param {boolean} [options.promoteLongs=true] Promotes Long values to number if they fit inside the 53 bits resolution.
  286. * @param {boolean} [options.promoteValues=true] Promotes BSON values to native types where possible, set to false to only receive wrapper types.
  287. * @param {boolean} [options.promoteBuffers=false] Promotes Binary BSON values to native Node Buffers.
  288. * @param {object} [options.collation] Specify collation (MongoDB 3.4 or higher) settings for update operation (see 3.4 documentation for available fields).
  289. * @param {string} [options.comment] Add a comment to an aggregation command
  290. * @param {string|object} [options.hint] Add an index selection hint to an aggregation command
  291. * @param {ClientSession} [options.session] optional session to use for this operation
  292. * @param {Database~aggregationCallback} callback The command result callback
  293. * @return {(null|AggregationCursor)}
  294. */
  295. Db.prototype.aggregate = function(pipeline, options, callback) {
  296. if (typeof options === 'function') {
  297. callback = options;
  298. options = {};
  299. }
  300. // If we have no options or callback we are doing
  301. // a cursor based aggregation
  302. if (options == null && callback == null) {
  303. options = {};
  304. }
  305. const cursor = new AggregationCursor(
  306. this.s.topology,
  307. new AggregateOperation(this, pipeline, options),
  308. options
  309. );
  310. // TODO: remove this when NODE-2074 is resolved
  311. if (typeof callback === 'function') {
  312. callback(null, cursor);
  313. return;
  314. }
  315. return cursor;
  316. };
  317. /**
  318. * Return the Admin db instance
  319. * @method
  320. * @return {Admin} return the new Admin db instance
  321. */
  322. Db.prototype.admin = function() {
  323. const Admin = require('./admin');
  324. return new Admin(this, this.s.topology, this.s.promiseLibrary);
  325. };
  326. /**
  327. * The callback format for the collection method, must be used if strict is specified
  328. * @callback Db~collectionResultCallback
  329. * @param {MongoError} error An error instance representing the error during the execution.
  330. * @param {Collection} collection The collection instance.
  331. */
  332. /**
  333. * The callback format for an aggregation call
  334. * @callback Database~aggregationCallback
  335. * @param {MongoError} error An error instance representing the error during the execution.
  336. * @param {AggregationCursor} cursor The cursor if the aggregation command was executed successfully.
  337. */
  338. const collectionKeys = [
  339. 'pkFactory',
  340. 'readPreference',
  341. 'serializeFunctions',
  342. 'strict',
  343. 'readConcern',
  344. 'ignoreUndefined',
  345. 'promoteValues',
  346. 'promoteBuffers',
  347. 'promoteLongs'
  348. ];
  349. /**
  350. * Fetch a specific collection (containing the actual collection information). If the application does not use strict mode you
  351. * can use it without a callback in the following way: `const collection = db.collection('mycollection');`
  352. *
  353. * @method
  354. * @param {string} name the collection name we wish to access.
  355. * @param {object} [options] Optional settings.
  356. * @param {(number|string)} [options.w] The write concern.
  357. * @param {number} [options.wtimeout] The write concern timeout.
  358. * @param {boolean} [options.j=false] Specify a journal write concern.
  359. * @param {boolean} [options.raw=false] Return document results as raw BSON buffers.
  360. * @param {object} [options.pkFactory] A primary key factory object for generation of custom _id keys.
  361. * @param {(ReadPreference|string)} [options.readPreference] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
  362. * @param {boolean} [options.serializeFunctions=false] Serialize functions on any object.
  363. * @param {boolean} [options.strict=false] Returns an error if the collection does not exist
  364. * @param {object} [options.readConcern] Specify a read concern for the collection. (only MongoDB 3.2 or higher supported)
  365. * @param {ReadConcernLevel} [options.readConcern.level='local'] Specify a read concern level for the collection operations (only MongoDB 3.2 or higher supported)
  366. * @param {Db~collectionResultCallback} [callback] The collection result callback
  367. * @return {Collection} return the new Collection instance if not in strict mode
  368. */
  369. Db.prototype.collection = function(name, options, callback) {
  370. if (typeof options === 'function') (callback = options), (options = {});
  371. options = options || {};
  372. options = Object.assign({}, options);
  373. // Set the promise library
  374. options.promiseLibrary = this.s.promiseLibrary;
  375. // If we have not set a collection level readConcern set the db level one
  376. options.readConcern = options.readConcern
  377. ? new ReadConcern(options.readConcern.level)
  378. : this.readConcern;
  379. // Do we have ignoreUndefined set
  380. if (this.s.options.ignoreUndefined) {
  381. options.ignoreUndefined = this.s.options.ignoreUndefined;
  382. }
  383. // Merge in all needed options and ensure correct writeConcern merging from db level
  384. options = mergeOptionsAndWriteConcern(options, this.s.options, collectionKeys, true);
  385. // Execute
  386. if (options == null || !options.strict) {
  387. try {
  388. const collection = new Collection(
  389. this,
  390. this.s.topology,
  391. this.databaseName,
  392. name,
  393. this.s.pkFactory,
  394. options
  395. );
  396. if (callback) callback(null, collection);
  397. return collection;
  398. } catch (err) {
  399. if (err instanceof MongoError && callback) return callback(err);
  400. throw err;
  401. }
  402. }
  403. // Strict mode
  404. if (typeof callback !== 'function') {
  405. throw toError(`A callback is required in strict mode. While getting collection ${name}`);
  406. }
  407. // Did the user destroy the topology
  408. if (this.serverConfig && this.serverConfig.isDestroyed()) {
  409. return callback(new MongoError('topology was destroyed'));
  410. }
  411. const listCollectionOptions = Object.assign({}, options, { nameOnly: true });
  412. // Strict mode
  413. this.listCollections({ name: name }, listCollectionOptions).toArray((err, collections) => {
  414. if (err != null) return handleCallback(callback, err, null);
  415. if (collections.length === 0)
  416. return handleCallback(
  417. callback,
  418. toError(`Collection ${name} does not exist. Currently in strict mode.`),
  419. null
  420. );
  421. try {
  422. return handleCallback(
  423. callback,
  424. null,
  425. new Collection(this, this.s.topology, this.databaseName, name, this.s.pkFactory, options)
  426. );
  427. } catch (err) {
  428. return handleCallback(callback, err, null);
  429. }
  430. });
  431. };
  432. /**
  433. * Create a new collection on a server with the specified options. Use this to create capped collections.
  434. * More information about command options available at https://docs.mongodb.com/manual/reference/command/create/
  435. *
  436. * @method
  437. * @param {string} name the collection name we wish to access.
  438. * @param {object} [options] Optional settings.
  439. * @param {(number|string)} [options.w] The write concern.
  440. * @param {number} [options.wtimeout] The write concern timeout.
  441. * @param {boolean} [options.j=false] Specify a journal write concern.
  442. * @param {boolean} [options.raw=false] Return document results as raw BSON buffers.
  443. * @param {object} [options.pkFactory] A primary key factory object for generation of custom _id keys.
  444. * @param {(ReadPreference|string)} [options.readPreference] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
  445. * @param {boolean} [options.serializeFunctions=false] Serialize functions on any object.
  446. * @param {boolean} [options.strict=false] Returns an error if the collection does not exist
  447. * @param {boolean} [options.capped=false] Create a capped collection.
  448. * @param {boolean} [options.autoIndexId=true] DEPRECATED: Create an index on the _id field of the document, True by default on MongoDB 2.6 - 3.0
  449. * @param {number} [options.size] The size of the capped collection in bytes.
  450. * @param {number} [options.max] The maximum number of documents in the capped collection.
  451. * @param {number} [options.flags] Optional. Available for the MMAPv1 storage engine only to set the usePowerOf2Sizes and the noPadding flag.
  452. * @param {object} [options.storageEngine] Allows users to specify configuration to the storage engine on a per-collection basis when creating a collection on MongoDB 3.0 or higher.
  453. * @param {object} [options.validator] Allows users to specify validation rules or expressions for the collection. For more information, see Document Validation on MongoDB 3.2 or higher.
  454. * @param {string} [options.validationLevel] Determines how strictly MongoDB applies the validation rules to existing documents during an update on MongoDB 3.2 or higher.
  455. * @param {string} [options.validationAction] Determines whether to error on invalid documents or just warn about the violations but allow invalid documents to be inserted on MongoDB 3.2 or higher.
  456. * @param {object} [options.indexOptionDefaults] Allows users to specify a default configuration for indexes when creating a collection on MongoDB 3.2 or higher.
  457. * @param {string} [options.viewOn] The name of the source collection or view from which to create the view. The name is not the full namespace of the collection or view; i.e. does not include the database name and implies the same database as the view to create on MongoDB 3.4 or higher.
  458. * @param {array} [options.pipeline] An array that consists of the aggregation pipeline stage. Creates the view by applying the specified pipeline to the viewOn collection or view on MongoDB 3.4 or higher.
  459. * @param {object} [options.collation] Specify collation (MongoDB 3.4 or higher) settings for update operation (see 3.4 documentation for available fields).
  460. * @param {ClientSession} [options.session] optional session to use for this operation
  461. * @param {Db~collectionResultCallback} [callback] The results callback
  462. * @return {Promise} returns Promise if no callback passed
  463. */
  464. Db.prototype.createCollection = deprecateOptions(
  465. {
  466. name: 'Db.createCollection',
  467. deprecatedOptions: ['autoIndexId'],
  468. optionsIndex: 1
  469. },
  470. function(name, options, callback) {
  471. if (typeof options === 'function') (callback = options), (options = {});
  472. options = options || {};
  473. options.promiseLibrary = options.promiseLibrary || this.s.promiseLibrary;
  474. options.readConcern = options.readConcern
  475. ? new ReadConcern(options.readConcern.level)
  476. : this.readConcern;
  477. const createCollectionOperation = new CreateCollectionOperation(this, name, options);
  478. return executeOperation(this.s.topology, createCollectionOperation, callback);
  479. }
  480. );
  481. /**
  482. * Get all the db statistics.
  483. *
  484. * @method
  485. * @param {object} [options] Optional settings.
  486. * @param {number} [options.scale] Divide the returned sizes by scale value.
  487. * @param {ClientSession} [options.session] optional session to use for this operation
  488. * @param {Db~resultCallback} [callback] The collection result callback
  489. * @return {Promise} returns Promise if no callback passed
  490. */
  491. Db.prototype.stats = function(options, callback) {
  492. if (typeof options === 'function') (callback = options), (options = {});
  493. options = options || {};
  494. // Build command object
  495. const commandObject = { dbStats: true };
  496. // Check if we have the scale value
  497. if (options['scale'] != null) commandObject['scale'] = options['scale'];
  498. // If we have a readPreference set
  499. if (options.readPreference == null && this.s.readPreference) {
  500. options.readPreference = this.s.readPreference;
  501. }
  502. const statsOperation = new CommandOperation(this, options, null, commandObject);
  503. // Execute the command
  504. return executeOperation(this.s.topology, statsOperation, callback);
  505. };
  506. /**
  507. * Get the list of all collection information for the specified db.
  508. *
  509. * @method
  510. * @param {object} [filter={}] Query to filter collections by
  511. * @param {object} [options] Optional settings.
  512. * @param {boolean} [options.nameOnly=false] Since 4.0: If true, will only return the collection name in the response, and will omit additional info
  513. * @param {number} [options.batchSize=1000] The batchSize for the returned command cursor or if pre 2.8 the systems batch collection
  514. * @param {(ReadPreference|string)} [options.readPreference] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
  515. * @param {ClientSession} [options.session] optional session to use for this operation
  516. * @return {CommandCursor}
  517. */
  518. Db.prototype.listCollections = function(filter, options) {
  519. filter = filter || {};
  520. options = options || {};
  521. return new CommandCursor(
  522. this.s.topology,
  523. new ListCollectionsOperation(this, filter, options),
  524. options
  525. );
  526. };
  527. /**
  528. * Evaluate JavaScript on the server
  529. *
  530. * @method
  531. * @param {Code} code JavaScript to execute on server.
  532. * @param {(object|array)} parameters The parameters for the call.
  533. * @param {object} [options] Optional settings.
  534. * @param {boolean} [options.nolock=false] Tell MongoDB not to block on the evaluation of the javascript.
  535. * @param {ClientSession} [options.session] optional session to use for this operation
  536. * @param {Db~resultCallback} [callback] The results callback
  537. * @deprecated Eval is deprecated on MongoDB 3.2 and forward
  538. * @return {Promise} returns Promise if no callback passed
  539. */
  540. Db.prototype.eval = deprecate(function(code, parameters, options, callback) {
  541. const args = Array.prototype.slice.call(arguments, 1);
  542. callback = typeof args[args.length - 1] === 'function' ? args.pop() : undefined;
  543. parameters = args.length ? args.shift() : parameters;
  544. options = args.length ? args.shift() || {} : {};
  545. return executeLegacyOperation(this.s.topology, evaluate, [
  546. this,
  547. code,
  548. parameters,
  549. options,
  550. callback
  551. ]);
  552. }, 'Db.eval is deprecated as of MongoDB version 3.2');
  553. /**
  554. * Rename a collection.
  555. *
  556. * @method
  557. * @param {string} fromCollection Name of current collection to rename.
  558. * @param {string} toCollection New name of of the collection.
  559. * @param {object} [options] Optional settings.
  560. * @param {boolean} [options.dropTarget=false] Drop the target name collection if it previously exists.
  561. * @param {ClientSession} [options.session] optional session to use for this operation
  562. * @param {Db~collectionResultCallback} [callback] The results callback
  563. * @return {Promise} returns Promise if no callback passed
  564. */
  565. Db.prototype.renameCollection = function(fromCollection, toCollection, options, callback) {
  566. if (typeof options === 'function') (callback = options), (options = {});
  567. options = Object.assign({}, options, { readPreference: ReadPreference.PRIMARY });
  568. // Add return new collection
  569. options.new_collection = true;
  570. const renameOperation = new RenameOperation(
  571. this.collection(fromCollection),
  572. toCollection,
  573. options
  574. );
  575. return executeOperation(this.s.topology, renameOperation, callback);
  576. };
  577. /**
  578. * Drop a collection from the database, removing it permanently. New accesses will create a new collection.
  579. *
  580. * @method
  581. * @param {string} name Name of collection to drop
  582. * @param {Object} [options] Optional settings
  583. * @param {WriteConcern} [options.writeConcern] A full WriteConcern object
  584. * @param {(number|string)} [options.w] The write concern
  585. * @param {number} [options.wtimeout] The write concern timeout
  586. * @param {boolean} [options.j] The journal write concern
  587. * @param {ClientSession} [options.session] optional session to use for this operation
  588. * @param {Db~resultCallback} [callback] The results callback
  589. * @return {Promise} returns Promise if no callback passed
  590. */
  591. Db.prototype.dropCollection = function(name, options, callback) {
  592. if (typeof options === 'function') (callback = options), (options = {});
  593. options = options || {};
  594. const dropCollectionOperation = new DropCollectionOperation(this, name, options);
  595. return executeOperation(this.s.topology, dropCollectionOperation, callback);
  596. };
  597. /**
  598. * Drop a database, removing it permanently from the server.
  599. *
  600. * @method
  601. * @param {Object} [options] Optional settings
  602. * @param {ClientSession} [options.session] optional session to use for this operation
  603. * @param {Db~resultCallback} [callback] The results callback
  604. * @return {Promise} returns Promise if no callback passed
  605. */
  606. Db.prototype.dropDatabase = function(options, callback) {
  607. if (typeof options === 'function') (callback = options), (options = {});
  608. options = options || {};
  609. const dropDatabaseOperation = new DropDatabaseOperation(this, options);
  610. return executeOperation(this.s.topology, dropDatabaseOperation, callback);
  611. };
  612. /**
  613. * Fetch all collections for the current db.
  614. *
  615. * @method
  616. * @param {Object} [options] Optional settings
  617. * @param {ClientSession} [options.session] optional session to use for this operation
  618. * @param {Db~collectionsResultCallback} [callback] The results callback
  619. * @return {Promise} returns Promise if no callback passed
  620. */
  621. Db.prototype.collections = function(options, callback) {
  622. if (typeof options === 'function') (callback = options), (options = {});
  623. options = options || {};
  624. const collectionsOperation = new CollectionsOperation(this, options);
  625. return executeOperation(this.s.topology, collectionsOperation, callback);
  626. };
  627. /**
  628. * Runs a command on the database as admin.
  629. * @method
  630. * @param {object} command The command hash
  631. * @param {object} [options] Optional settings.
  632. * @param {(ReadPreference|string)} [options.readPreference] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
  633. * @param {ClientSession} [options.session] optional session to use for this operation
  634. * @param {Db~resultCallback} [callback] The command result callback
  635. * @return {Promise} returns Promise if no callback passed
  636. */
  637. Db.prototype.executeDbAdminCommand = function(selector, options, callback) {
  638. if (typeof options === 'function') (callback = options), (options = {});
  639. options = options || {};
  640. options.readPreference = resolveReadPreference(this, options);
  641. const executeDbAdminCommandOperation = new ExecuteDbAdminCommandOperation(
  642. this,
  643. selector,
  644. options
  645. );
  646. return executeOperation(this.s.topology, executeDbAdminCommandOperation, callback);
  647. };
  648. /**
  649. * Creates an index on the db and collection.
  650. * @method
  651. * @param {string} name Name of the collection to create the index on.
  652. * @param {(string|object)} fieldOrSpec Defines the index.
  653. * @param {object} [options] Optional settings.
  654. * @param {(number|string)} [options.w] The write concern.
  655. * @param {number} [options.wtimeout] The write concern timeout.
  656. * @param {boolean} [options.j=false] Specify a journal write concern.
  657. * @param {boolean} [options.unique=false] Creates an unique index.
  658. * @param {boolean} [options.sparse=false] Creates a sparse index.
  659. * @param {boolean} [options.background=false] Creates the index in the background, yielding whenever possible.
  660. * @param {boolean} [options.dropDups=false] A unique index cannot be created on a key that has pre-existing duplicate values. If you would like to create the index anyway, keeping the first document the database indexes and deleting all subsequent documents that have duplicate value
  661. * @param {number} [options.min] For geospatial indexes set the lower bound for the co-ordinates.
  662. * @param {number} [options.max] For geospatial indexes set the high bound for the co-ordinates.
  663. * @param {number} [options.v] Specify the format version of the indexes.
  664. * @param {number} [options.expireAfterSeconds] Allows you to expire data on indexes applied to a data (MongoDB 2.2 or higher)
  665. * @param {string} [options.name] Override the autogenerated index name (useful if the resulting name is larger than 128 bytes)
  666. * @param {object} [options.partialFilterExpression] Creates a partial index based on the given filter object (MongoDB 3.2 or higher)
  667. * @param {ClientSession} [options.session] optional session to use for this operation
  668. * @param {Db~resultCallback} [callback] The command result callback
  669. * @return {Promise} returns Promise if no callback passed
  670. */
  671. Db.prototype.createIndex = function(name, fieldOrSpec, options, callback) {
  672. if (typeof options === 'function') (callback = options), (options = {});
  673. options = options ? Object.assign({}, options) : {};
  674. const createIndexOperation = new CreateIndexOperation(this, name, fieldOrSpec, options);
  675. return executeOperation(this.s.topology, createIndexOperation, callback);
  676. };
  677. /**
  678. * Ensures that an index exists, if it does not it creates it
  679. * @method
  680. * @deprecated since version 2.0
  681. * @param {string} name The index name
  682. * @param {(string|object)} fieldOrSpec Defines the index.
  683. * @param {object} [options] Optional settings.
  684. * @param {(number|string)} [options.w] The write concern.
  685. * @param {number} [options.wtimeout] The write concern timeout.
  686. * @param {boolean} [options.j=false] Specify a journal write concern.
  687. * @param {boolean} [options.unique=false] Creates an unique index.
  688. * @param {boolean} [options.sparse=false] Creates a sparse index.
  689. * @param {boolean} [options.background=false] Creates the index in the background, yielding whenever possible.
  690. * @param {boolean} [options.dropDups=false] A unique index cannot be created on a key that has pre-existing duplicate values. If you would like to create the index anyway, keeping the first document the database indexes and deleting all subsequent documents that have duplicate value
  691. * @param {number} [options.min] For geospatial indexes set the lower bound for the co-ordinates.
  692. * @param {number} [options.max] For geospatial indexes set the high bound for the co-ordinates.
  693. * @param {number} [options.v] Specify the format version of the indexes.
  694. * @param {number} [options.expireAfterSeconds] Allows you to expire data on indexes applied to a data (MongoDB 2.2 or higher)
  695. * @param {number} [options.name] Override the autogenerated index name (useful if the resulting name is larger than 128 bytes)
  696. * @param {ClientSession} [options.session] optional session to use for this operation
  697. * @param {Db~resultCallback} [callback] The command result callback
  698. * @return {Promise} returns Promise if no callback passed
  699. */
  700. Db.prototype.ensureIndex = deprecate(function(name, fieldOrSpec, options, callback) {
  701. if (typeof options === 'function') (callback = options), (options = {});
  702. options = options || {};
  703. return executeLegacyOperation(this.s.topology, ensureIndex, [
  704. this,
  705. name,
  706. fieldOrSpec,
  707. options,
  708. callback
  709. ]);
  710. }, 'Db.ensureIndex is deprecated as of MongoDB version 3.0 / driver version 2.0');
  711. Db.prototype.addChild = function(db) {
  712. if (this.s.parentDb) return this.s.parentDb.addChild(db);
  713. this.s.children.push(db);
  714. };
  715. /**
  716. * Add a user to the database.
  717. * @method
  718. * @param {string} username The username.
  719. * @param {string} password The password.
  720. * @param {object} [options] Optional settings.
  721. * @param {(number|string)} [options.w] The write concern.
  722. * @param {number} [options.wtimeout] The write concern timeout.
  723. * @param {boolean} [options.j=false] Specify a journal write concern.
  724. * @param {object} [options.customData] Custom data associated with the user (only Mongodb 2.6 or higher)
  725. * @param {object[]} [options.roles] Roles associated with the created user (only Mongodb 2.6 or higher)
  726. * @param {ClientSession} [options.session] optional session to use for this operation
  727. * @param {Db~resultCallback} [callback] The command result callback
  728. * @return {Promise} returns Promise if no callback passed
  729. */
  730. Db.prototype.addUser = function(username, password, options, callback) {
  731. if (typeof options === 'function') (callback = options), (options = {});
  732. options = options || {};
  733. // Special case where there is no password ($external users)
  734. if (typeof username === 'string' && password != null && typeof password === 'object') {
  735. options = password;
  736. password = null;
  737. }
  738. const addUserOperation = new AddUserOperation(this, username, password, options);
  739. return executeOperation(this.s.topology, addUserOperation, callback);
  740. };
  741. /**
  742. * Remove a user from a database
  743. * @method
  744. * @param {string} username The username.
  745. * @param {object} [options] Optional settings.
  746. * @param {(number|string)} [options.w] The write concern.
  747. * @param {number} [options.wtimeout] The write concern timeout.
  748. * @param {boolean} [options.j=false] Specify a journal write concern.
  749. * @param {ClientSession} [options.session] optional session to use for this operation
  750. * @param {Db~resultCallback} [callback] The command result callback
  751. * @return {Promise} returns Promise if no callback passed
  752. */
  753. Db.prototype.removeUser = function(username, options, callback) {
  754. if (typeof options === 'function') (callback = options), (options = {});
  755. options = options || {};
  756. const removeUserOperation = new RemoveUserOperation(this, username, options);
  757. return executeOperation(this.s.topology, removeUserOperation, callback);
  758. };
  759. /**
  760. * Set the current profiling level of MongoDB
  761. *
  762. * @param {string} level The new profiling level (off, slow_only, all).
  763. * @param {Object} [options] Optional settings
  764. * @param {ClientSession} [options.session] optional session to use for this operation
  765. * @param {Db~resultCallback} [callback] The command result callback.
  766. * @return {Promise} returns Promise if no callback passed
  767. */
  768. Db.prototype.setProfilingLevel = function(level, options, callback) {
  769. if (typeof options === 'function') (callback = options), (options = {});
  770. options = options || {};
  771. const setProfilingLevelOperation = new SetProfilingLevelOperation(this, level, options);
  772. return executeOperation(this.s.topology, setProfilingLevelOperation, callback);
  773. };
  774. /**
  775. * Retrieve the current profiling information for MongoDB
  776. *
  777. * @param {Object} [options] Optional settings
  778. * @param {ClientSession} [options.session] optional session to use for this operation
  779. * @param {Db~resultCallback} [callback] The command result callback.
  780. * @return {Promise} returns Promise if no callback passed
  781. * @deprecated Query the system.profile collection directly.
  782. */
  783. Db.prototype.profilingInfo = deprecate(function(options, callback) {
  784. if (typeof options === 'function') (callback = options), (options = {});
  785. options = options || {};
  786. return executeLegacyOperation(this.s.topology, profilingInfo, [this, options, callback]);
  787. }, 'Db.profilingInfo is deprecated. Query the system.profile collection directly.');
  788. /**
  789. * Retrieve the current profiling Level for MongoDB
  790. *
  791. * @param {Object} [options] Optional settings
  792. * @param {ClientSession} [options.session] optional session to use for this operation
  793. * @param {Db~resultCallback} [callback] The command result callback
  794. * @return {Promise} returns Promise if no callback passed
  795. */
  796. Db.prototype.profilingLevel = function(options, callback) {
  797. if (typeof options === 'function') (callback = options), (options = {});
  798. options = options || {};
  799. const profilingLevelOperation = new ProfilingLevelOperation(this, options);
  800. return executeOperation(this.s.topology, profilingLevelOperation, callback);
  801. };
  802. /**
  803. * Retrieves this collections index info.
  804. * @method
  805. * @param {string} name The name of the collection.
  806. * @param {object} [options] Optional settings.
  807. * @param {boolean} [options.full=false] Returns the full raw index information.
  808. * @param {(ReadPreference|string)} [options.readPreference] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
  809. * @param {ClientSession} [options.session] optional session to use for this operation
  810. * @param {Db~resultCallback} [callback] The command result callback
  811. * @return {Promise} returns Promise if no callback passed
  812. */
  813. Db.prototype.indexInformation = function(name, options, callback) {
  814. if (typeof options === 'function') (callback = options), (options = {});
  815. options = options || {};
  816. const indexInformationOperation = new IndexInformationOperation(this, name, options);
  817. return executeOperation(this.s.topology, indexInformationOperation, callback);
  818. };
  819. /**
  820. * Unref all sockets
  821. * @method
  822. */
  823. Db.prototype.unref = function() {
  824. this.s.topology.unref();
  825. };
  826. /**
  827. * Create a new Change Stream, watching for new changes (insertions, updates, replacements, deletions, and invalidations) in this database. Will ignore all changes to system collections.
  828. * @method
  829. * @since 3.1.0
  830. * @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.
  831. * @param {object} [options] Optional settings
  832. * @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.
  833. * @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.
  834. * @param {number} [options.maxAwaitTimeMS] The maximum amount of time for the server to wait on new documents to satisfy a change stream query
  835. * @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}.
  836. * @param {object} [options.collation] Specify collation settings for operation. See {@link https://docs.mongodb.com/manual/reference/command/aggregate|aggregation documentation}.
  837. * @param {ReadPreference} [options.readPreference] The read preference. Defaults to the read preference of the database. See {@link https://docs.mongodb.com/manual/reference/read-preference|read preference documentation}.
  838. * @param {Timestamp} [options.startAtOperationTime] receive change events that occur after the specified timestamp
  839. * @param {ClientSession} [options.session] optional session to use for this operation
  840. * @return {ChangeStream} a ChangeStream instance.
  841. */
  842. Db.prototype.watch = function(pipeline, options) {
  843. pipeline = pipeline || [];
  844. options = options || {};
  845. // Allow optionally not specifying a pipeline
  846. if (!Array.isArray(pipeline)) {
  847. options = pipeline;
  848. pipeline = [];
  849. }
  850. return new ChangeStream(this, pipeline, options);
  851. };
  852. /**
  853. * Return the db logger
  854. * @method
  855. * @return {Logger} return the db logger
  856. * @ignore
  857. */
  858. Db.prototype.getLogger = function() {
  859. return this.s.logger;
  860. };
  861. /**
  862. * Db close event
  863. *
  864. * Emitted after a socket closed against a single server or mongos proxy.
  865. *
  866. * @event Db#close
  867. * @type {MongoError}
  868. */
  869. /**
  870. * Db reconnect event
  871. *
  872. * * Server: Emitted when the driver has reconnected and re-authenticated.
  873. * * ReplicaSet: N/A
  874. * * Mongos: Emitted when the driver reconnects and re-authenticates successfully against a Mongos.
  875. *
  876. * @event Db#reconnect
  877. * @type {object}
  878. */
  879. /**
  880. * Db error event
  881. *
  882. * Emitted after an error occurred against a single server or mongos proxy.
  883. *
  884. * @event Db#error
  885. * @type {MongoError}
  886. */
  887. /**
  888. * Db timeout event
  889. *
  890. * Emitted after a socket timeout occurred against a single server or mongos proxy.
  891. *
  892. * @event Db#timeout
  893. * @type {MongoError}
  894. */
  895. /**
  896. * Db parseError event
  897. *
  898. * The parseError event is emitted if the driver detects illegal or corrupt BSON being received from the server.
  899. *
  900. * @event Db#parseError
  901. * @type {MongoError}
  902. */
  903. /**
  904. * Db fullsetup event, emitted when all servers in the topology have been connected to at start up time.
  905. *
  906. * * Server: Emitted when the driver has connected to the single server and has authenticated.
  907. * * ReplSet: Emitted after the driver has attempted to connect to all replicaset members.
  908. * * Mongos: Emitted after the driver has attempted to connect to all mongos proxies.
  909. *
  910. * @event Db#fullsetup
  911. * @type {Db}
  912. */
  913. // Constants
  914. Db.SYSTEM_NAMESPACE_COLLECTION = CONSTANTS.SYSTEM_NAMESPACE_COLLECTION;
  915. Db.SYSTEM_INDEX_COLLECTION = CONSTANTS.SYSTEM_INDEX_COLLECTION;
  916. Db.SYSTEM_PROFILE_COLLECTION = CONSTANTS.SYSTEM_PROFILE_COLLECTION;
  917. Db.SYSTEM_USER_COLLECTION = CONSTANTS.SYSTEM_USER_COLLECTION;
  918. Db.SYSTEM_COMMAND_COLLECTION = CONSTANTS.SYSTEM_COMMAND_COLLECTION;
  919. Db.SYSTEM_JS_COLLECTION = CONSTANTS.SYSTEM_JS_COLLECTION;
  920. module.exports = Db;