collection.ts 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142
  1. import { type BSONSerializeOptions, type Document, resolveBSONOptions } from './bson';
  2. import type { AnyBulkWriteOperation, BulkWriteOptions, BulkWriteResult } from './bulk/common';
  3. import { OrderedBulkOperation } from './bulk/ordered';
  4. import { UnorderedBulkOperation } from './bulk/unordered';
  5. import { ChangeStream, type ChangeStreamDocument, type ChangeStreamOptions } from './change_stream';
  6. import { AggregationCursor } from './cursor/aggregation_cursor';
  7. import { FindCursor } from './cursor/find_cursor';
  8. import { ListIndexesCursor } from './cursor/list_indexes_cursor';
  9. import {
  10. ListSearchIndexesCursor,
  11. type ListSearchIndexesOptions
  12. } from './cursor/list_search_indexes_cursor';
  13. import type { Db } from './db';
  14. import { MongoInvalidArgumentError } from './error';
  15. import type { MongoClient, PkFactory } from './mongo_client';
  16. import type {
  17. Filter,
  18. Flatten,
  19. OptionalUnlessRequiredId,
  20. TODO_NODE_3286,
  21. UpdateFilter,
  22. WithId,
  23. WithoutId
  24. } from './mongo_types';
  25. import type { AggregateOptions } from './operations/aggregate';
  26. import { BulkWriteOperation } from './operations/bulk_write';
  27. import type { IndexInformationOptions } from './operations/common_functions';
  28. import { CountOperation, type CountOptions } from './operations/count';
  29. import { CountDocumentsOperation, type CountDocumentsOptions } from './operations/count_documents';
  30. import {
  31. DeleteManyOperation,
  32. DeleteOneOperation,
  33. type DeleteOptions,
  34. type DeleteResult
  35. } from './operations/delete';
  36. import { DistinctOperation, type DistinctOptions } from './operations/distinct';
  37. import { DropCollectionOperation, type DropCollectionOptions } from './operations/drop';
  38. import {
  39. EstimatedDocumentCountOperation,
  40. type EstimatedDocumentCountOptions
  41. } from './operations/estimated_document_count';
  42. import { executeOperation } from './operations/execute_operation';
  43. import type { FindOptions } from './operations/find';
  44. import {
  45. FindOneAndDeleteOperation,
  46. type FindOneAndDeleteOptions,
  47. FindOneAndReplaceOperation,
  48. type FindOneAndReplaceOptions,
  49. FindOneAndUpdateOperation,
  50. type FindOneAndUpdateOptions
  51. } from './operations/find_and_modify';
  52. import {
  53. CreateIndexesOperation,
  54. type CreateIndexesOptions,
  55. CreateIndexOperation,
  56. DropIndexesOperation,
  57. type DropIndexesOptions,
  58. DropIndexOperation,
  59. type IndexDescription,
  60. IndexesOperation,
  61. IndexExistsOperation,
  62. IndexInformationOperation,
  63. type IndexSpecification,
  64. type ListIndexesOptions
  65. } from './operations/indexes';
  66. import {
  67. InsertManyOperation,
  68. type InsertManyResult,
  69. InsertOneOperation,
  70. type InsertOneOptions,
  71. type InsertOneResult
  72. } from './operations/insert';
  73. import { IsCappedOperation } from './operations/is_capped';
  74. import type { Hint, OperationOptions } from './operations/operation';
  75. import { OptionsOperation } from './operations/options_operation';
  76. import { RenameOperation, type RenameOptions } from './operations/rename';
  77. import {
  78. CreateSearchIndexesOperation,
  79. type SearchIndexDescription
  80. } from './operations/search_indexes/create';
  81. import { DropSearchIndexOperation } from './operations/search_indexes/drop';
  82. import { UpdateSearchIndexOperation } from './operations/search_indexes/update';
  83. import { type CollStats, CollStatsOperation, type CollStatsOptions } from './operations/stats';
  84. import {
  85. ReplaceOneOperation,
  86. type ReplaceOptions,
  87. UpdateManyOperation,
  88. UpdateOneOperation,
  89. type UpdateOptions,
  90. type UpdateResult
  91. } from './operations/update';
  92. import { ReadConcern, type ReadConcernLike } from './read_concern';
  93. import { ReadPreference, type ReadPreferenceLike } from './read_preference';
  94. import {
  95. checkCollectionName,
  96. DEFAULT_PK_FACTORY,
  97. MongoDBCollectionNamespace,
  98. normalizeHintField,
  99. resolveOptions
  100. } from './utils';
  101. import { WriteConcern, type WriteConcernOptions } from './write_concern';
  102. /** @public */
  103. export interface ModifyResult<TSchema = Document> {
  104. value: WithId<TSchema> | null;
  105. lastErrorObject?: Document;
  106. ok: 0 | 1;
  107. }
  108. /** @public */
  109. export interface CollectionOptions extends BSONSerializeOptions, WriteConcernOptions {
  110. /** Specify a read concern for the collection. (only MongoDB 3.2 or higher supported) */
  111. readConcern?: ReadConcernLike;
  112. /** The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). */
  113. readPreference?: ReadPreferenceLike;
  114. }
  115. /** @internal */
  116. export interface CollectionPrivate {
  117. pkFactory: PkFactory;
  118. db: Db;
  119. options: any;
  120. namespace: MongoDBCollectionNamespace;
  121. readPreference?: ReadPreference;
  122. bsonOptions: BSONSerializeOptions;
  123. collectionHint?: Hint;
  124. readConcern?: ReadConcern;
  125. writeConcern?: WriteConcern;
  126. }
  127. /**
  128. * The **Collection** class is an internal class that embodies a MongoDB collection
  129. * allowing for insert/find/update/delete and other command operation on that MongoDB collection.
  130. *
  131. * **COLLECTION Cannot directly be instantiated**
  132. * @public
  133. *
  134. * @example
  135. * ```ts
  136. * import { MongoClient } from 'mongodb';
  137. *
  138. * interface Pet {
  139. * name: string;
  140. * kind: 'dog' | 'cat' | 'fish';
  141. * }
  142. *
  143. * const client = new MongoClient('mongodb://localhost:27017');
  144. * const pets = client.db().collection<Pet>('pets');
  145. *
  146. * const petCursor = pets.find();
  147. *
  148. * for await (const pet of petCursor) {
  149. * console.log(`${pet.name} is a ${pet.kind}!`);
  150. * }
  151. * ```
  152. */
  153. export class Collection<TSchema extends Document = Document> {
  154. /** @internal */
  155. s: CollectionPrivate;
  156. /** @internal */
  157. client: MongoClient;
  158. /**
  159. * Create a new Collection instance
  160. * @internal
  161. */
  162. constructor(db: Db, name: string, options?: CollectionOptions) {
  163. checkCollectionName(name);
  164. // Internal state
  165. this.s = {
  166. db,
  167. options,
  168. namespace: new MongoDBCollectionNamespace(db.databaseName, name),
  169. pkFactory: db.options?.pkFactory ?? DEFAULT_PK_FACTORY,
  170. readPreference: ReadPreference.fromOptions(options),
  171. bsonOptions: resolveBSONOptions(options, db),
  172. readConcern: ReadConcern.fromOptions(options),
  173. writeConcern: WriteConcern.fromOptions(options)
  174. };
  175. this.client = db.client;
  176. }
  177. /**
  178. * The name of the database this collection belongs to
  179. */
  180. get dbName(): string {
  181. return this.s.namespace.db;
  182. }
  183. /**
  184. * The name of this collection
  185. */
  186. get collectionName(): string {
  187. return this.s.namespace.collection;
  188. }
  189. /**
  190. * The namespace of this collection, in the format `${this.dbName}.${this.collectionName}`
  191. */
  192. get namespace(): string {
  193. return this.fullNamespace.toString();
  194. }
  195. /**
  196. * @internal
  197. *
  198. * The `MongoDBNamespace` for the collection.
  199. */
  200. get fullNamespace(): MongoDBCollectionNamespace {
  201. return this.s.namespace;
  202. }
  203. /**
  204. * The current readConcern of the collection. If not explicitly defined for
  205. * this collection, will be inherited from the parent DB
  206. */
  207. get readConcern(): ReadConcern | undefined {
  208. if (this.s.readConcern == null) {
  209. return this.s.db.readConcern;
  210. }
  211. return this.s.readConcern;
  212. }
  213. /**
  214. * The current readPreference of the collection. If not explicitly defined for
  215. * this collection, will be inherited from the parent DB
  216. */
  217. get readPreference(): ReadPreference | undefined {
  218. if (this.s.readPreference == null) {
  219. return this.s.db.readPreference;
  220. }
  221. return this.s.readPreference;
  222. }
  223. get bsonOptions(): BSONSerializeOptions {
  224. return this.s.bsonOptions;
  225. }
  226. /**
  227. * The current writeConcern of the collection. If not explicitly defined for
  228. * this collection, will be inherited from the parent DB
  229. */
  230. get writeConcern(): WriteConcern | undefined {
  231. if (this.s.writeConcern == null) {
  232. return this.s.db.writeConcern;
  233. }
  234. return this.s.writeConcern;
  235. }
  236. /** The current index hint for the collection */
  237. get hint(): Hint | undefined {
  238. return this.s.collectionHint;
  239. }
  240. set hint(v: Hint | undefined) {
  241. this.s.collectionHint = normalizeHintField(v);
  242. }
  243. /**
  244. * Inserts a single document into MongoDB. If documents passed in do not contain the **_id** field,
  245. * one will be added to each of the documents missing it by the driver, mutating the document. This behavior
  246. * can be overridden by setting the **forceServerObjectId** flag.
  247. *
  248. * @param doc - The document to insert
  249. * @param options - Optional settings for the command
  250. */
  251. async insertOne(
  252. doc: OptionalUnlessRequiredId<TSchema>,
  253. options?: InsertOneOptions
  254. ): Promise<InsertOneResult<TSchema>> {
  255. return executeOperation(
  256. this.client,
  257. new InsertOneOperation(
  258. this as TODO_NODE_3286,
  259. doc,
  260. resolveOptions(this, options)
  261. ) as TODO_NODE_3286
  262. );
  263. }
  264. /**
  265. * Inserts an array of documents into MongoDB. If documents passed in do not contain the **_id** field,
  266. * one will be added to each of the documents missing it by the driver, mutating the document. This behavior
  267. * can be overridden by setting the **forceServerObjectId** flag.
  268. *
  269. * @param docs - The documents to insert
  270. * @param options - Optional settings for the command
  271. */
  272. async insertMany(
  273. docs: OptionalUnlessRequiredId<TSchema>[],
  274. options?: BulkWriteOptions
  275. ): Promise<InsertManyResult<TSchema>> {
  276. return executeOperation(
  277. this.client,
  278. new InsertManyOperation(
  279. this as TODO_NODE_3286,
  280. docs,
  281. resolveOptions(this, options ?? { ordered: true })
  282. ) as TODO_NODE_3286
  283. );
  284. }
  285. /**
  286. * Perform a bulkWrite operation without a fluent API
  287. *
  288. * Legal operation types are
  289. * - `insertOne`
  290. * - `replaceOne`
  291. * - `updateOne`
  292. * - `updateMany`
  293. * - `deleteOne`
  294. * - `deleteMany`
  295. *
  296. * If documents passed in do not contain the **_id** field,
  297. * one will be added to each of the documents missing it by the driver, mutating the document. This behavior
  298. * can be overridden by setting the **forceServerObjectId** flag.
  299. *
  300. * @param operations - Bulk operations to perform
  301. * @param options - Optional settings for the command
  302. * @throws MongoDriverError if operations is not an array
  303. */
  304. async bulkWrite(
  305. operations: AnyBulkWriteOperation<TSchema>[],
  306. options?: BulkWriteOptions
  307. ): Promise<BulkWriteResult> {
  308. if (!Array.isArray(operations)) {
  309. throw new MongoInvalidArgumentError('Argument "operations" must be an array of documents');
  310. }
  311. return executeOperation(
  312. this.client,
  313. new BulkWriteOperation(
  314. this as TODO_NODE_3286,
  315. operations as TODO_NODE_3286,
  316. resolveOptions(this, options ?? { ordered: true })
  317. )
  318. );
  319. }
  320. /**
  321. * Update a single document in a collection
  322. *
  323. * @param filter - The filter used to select the document to update
  324. * @param update - The update operations to be applied to the document
  325. * @param options - Optional settings for the command
  326. */
  327. async updateOne(
  328. filter: Filter<TSchema>,
  329. update: UpdateFilter<TSchema> | Partial<TSchema>,
  330. options?: UpdateOptions
  331. ): Promise<UpdateResult<TSchema>> {
  332. return executeOperation(
  333. this.client,
  334. new UpdateOneOperation(
  335. this as TODO_NODE_3286,
  336. filter,
  337. update,
  338. resolveOptions(this, options)
  339. ) as TODO_NODE_3286
  340. );
  341. }
  342. /**
  343. * Replace a document in a collection with another document
  344. *
  345. * @param filter - The filter used to select the document to replace
  346. * @param replacement - The Document that replaces the matching document
  347. * @param options - Optional settings for the command
  348. */
  349. async replaceOne(
  350. filter: Filter<TSchema>,
  351. replacement: WithoutId<TSchema>,
  352. options?: ReplaceOptions
  353. ): Promise<UpdateResult<TSchema> | Document> {
  354. return executeOperation(
  355. this.client,
  356. new ReplaceOneOperation(
  357. this as TODO_NODE_3286,
  358. filter,
  359. replacement,
  360. resolveOptions(this, options)
  361. )
  362. );
  363. }
  364. /**
  365. * Update multiple documents in a collection
  366. *
  367. * @param filter - The filter used to select the documents to update
  368. * @param update - The update operations to be applied to the documents
  369. * @param options - Optional settings for the command
  370. */
  371. async updateMany(
  372. filter: Filter<TSchema>,
  373. update: UpdateFilter<TSchema>,
  374. options?: UpdateOptions
  375. ): Promise<UpdateResult<TSchema>> {
  376. return executeOperation(
  377. this.client,
  378. new UpdateManyOperation(
  379. this as TODO_NODE_3286,
  380. filter,
  381. update,
  382. resolveOptions(this, options)
  383. ) as TODO_NODE_3286
  384. );
  385. }
  386. /**
  387. * Delete a document from a collection
  388. *
  389. * @param filter - The filter used to select the document to remove
  390. * @param options - Optional settings for the command
  391. */
  392. async deleteOne(
  393. filter: Filter<TSchema> = {},
  394. options: DeleteOptions = {}
  395. ): Promise<DeleteResult> {
  396. return executeOperation(
  397. this.client,
  398. new DeleteOneOperation(this as TODO_NODE_3286, filter, resolveOptions(this, options))
  399. );
  400. }
  401. /**
  402. * Delete multiple documents from a collection
  403. *
  404. * @param filter - The filter used to select the documents to remove
  405. * @param options - Optional settings for the command
  406. */
  407. async deleteMany(
  408. filter: Filter<TSchema> = {},
  409. options: DeleteOptions = {}
  410. ): Promise<DeleteResult> {
  411. return executeOperation(
  412. this.client,
  413. new DeleteManyOperation(this as TODO_NODE_3286, filter, resolveOptions(this, options))
  414. );
  415. }
  416. /**
  417. * Rename the collection.
  418. *
  419. * @remarks
  420. * This operation does not inherit options from the Db or MongoClient.
  421. *
  422. * @param newName - New name of of the collection.
  423. * @param options - Optional settings for the command
  424. */
  425. async rename(newName: string, options?: RenameOptions): Promise<Collection> {
  426. // Intentionally, we do not inherit options from parent for this operation.
  427. return executeOperation(
  428. this.client,
  429. new RenameOperation(this as TODO_NODE_3286, newName, {
  430. ...options,
  431. readPreference: ReadPreference.PRIMARY
  432. }) as TODO_NODE_3286
  433. );
  434. }
  435. /**
  436. * Drop the collection from the database, removing it permanently. New accesses will create a new collection.
  437. *
  438. * @param options - Optional settings for the command
  439. */
  440. async drop(options?: DropCollectionOptions): Promise<boolean> {
  441. return executeOperation(
  442. this.client,
  443. new DropCollectionOperation(this.s.db, this.collectionName, options)
  444. );
  445. }
  446. /**
  447. * Fetches the first document that matches the filter
  448. *
  449. * @param filter - Query for find Operation
  450. * @param options - Optional settings for the command
  451. */
  452. async findOne(): Promise<WithId<TSchema> | null>;
  453. async findOne(filter: Filter<TSchema>): Promise<WithId<TSchema> | null>;
  454. async findOne(filter: Filter<TSchema>, options: FindOptions): Promise<WithId<TSchema> | null>;
  455. // allow an override of the schema.
  456. async findOne<T = TSchema>(): Promise<T | null>;
  457. async findOne<T = TSchema>(filter: Filter<TSchema>): Promise<T | null>;
  458. async findOne<T = TSchema>(filter: Filter<TSchema>, options?: FindOptions): Promise<T | null>;
  459. async findOne(
  460. filter: Filter<TSchema> = {},
  461. options: FindOptions = {}
  462. ): Promise<WithId<TSchema> | null> {
  463. return this.find(filter, options).limit(-1).batchSize(1).next();
  464. }
  465. /**
  466. * Creates a cursor for a filter that can be used to iterate over results from MongoDB
  467. *
  468. * @param filter - The filter predicate. If unspecified, then all documents in the collection will match the predicate
  469. */
  470. find(): FindCursor<WithId<TSchema>>;
  471. find(filter: Filter<TSchema>, options?: FindOptions): FindCursor<WithId<TSchema>>;
  472. find<T extends Document>(filter: Filter<TSchema>, options?: FindOptions): FindCursor<T>;
  473. find(filter: Filter<TSchema> = {}, options: FindOptions = {}): FindCursor<WithId<TSchema>> {
  474. return new FindCursor<WithId<TSchema>>(
  475. this.client,
  476. this.s.namespace,
  477. filter,
  478. resolveOptions(this as TODO_NODE_3286, options)
  479. );
  480. }
  481. /**
  482. * Returns the options of the collection.
  483. *
  484. * @param options - Optional settings for the command
  485. */
  486. async options(options?: OperationOptions): Promise<Document> {
  487. return executeOperation(
  488. this.client,
  489. new OptionsOperation(this as TODO_NODE_3286, resolveOptions(this, options))
  490. );
  491. }
  492. /**
  493. * Returns if the collection is a capped collection
  494. *
  495. * @param options - Optional settings for the command
  496. */
  497. async isCapped(options?: OperationOptions): Promise<boolean> {
  498. return executeOperation(
  499. this.client,
  500. new IsCappedOperation(this as TODO_NODE_3286, resolveOptions(this, options))
  501. );
  502. }
  503. /**
  504. * Creates an index on the db and collection collection.
  505. *
  506. * @param indexSpec - The field name or index specification to create an index for
  507. * @param options - Optional settings for the command
  508. *
  509. * @example
  510. * ```ts
  511. * const collection = client.db('foo').collection('bar');
  512. *
  513. * await collection.createIndex({ a: 1, b: -1 });
  514. *
  515. * // Alternate syntax for { c: 1, d: -1 } that ensures order of indexes
  516. * await collection.createIndex([ [c, 1], [d, -1] ]);
  517. *
  518. * // Equivalent to { e: 1 }
  519. * await collection.createIndex('e');
  520. *
  521. * // Equivalent to { f: 1, g: 1 }
  522. * await collection.createIndex(['f', 'g'])
  523. *
  524. * // Equivalent to { h: 1, i: -1 }
  525. * await collection.createIndex([ { h: 1 }, { i: -1 } ]);
  526. *
  527. * // Equivalent to { j: 1, k: -1, l: 2d }
  528. * await collection.createIndex(['j', ['k', -1], { l: '2d' }])
  529. * ```
  530. */
  531. async createIndex(
  532. indexSpec: IndexSpecification,
  533. options?: CreateIndexesOptions
  534. ): Promise<string> {
  535. return executeOperation(
  536. this.client,
  537. new CreateIndexOperation(
  538. this as TODO_NODE_3286,
  539. this.collectionName,
  540. indexSpec,
  541. resolveOptions(this, options)
  542. )
  543. );
  544. }
  545. /**
  546. * Creates multiple indexes in the collection, this method is only supported for
  547. * MongoDB 2.6 or higher. Earlier version of MongoDB will throw a command not supported
  548. * error.
  549. *
  550. * **Note**: Unlike {@link Collection#createIndex| createIndex}, this function takes in raw index specifications.
  551. * Index specifications are defined {@link https://www.mongodb.com/docs/manual/reference/command/createIndexes/| here}.
  552. *
  553. * @param indexSpecs - An array of index specifications to be created
  554. * @param options - Optional settings for the command
  555. *
  556. * @example
  557. * ```ts
  558. * const collection = client.db('foo').collection('bar');
  559. * await collection.createIndexes([
  560. * // Simple index on field fizz
  561. * {
  562. * key: { fizz: 1 },
  563. * }
  564. * // wildcard index
  565. * {
  566. * key: { '$**': 1 }
  567. * },
  568. * // named index on darmok and jalad
  569. * {
  570. * key: { darmok: 1, jalad: -1 }
  571. * name: 'tanagra'
  572. * }
  573. * ]);
  574. * ```
  575. */
  576. async createIndexes(
  577. indexSpecs: IndexDescription[],
  578. options?: CreateIndexesOptions
  579. ): Promise<string[]> {
  580. return executeOperation(
  581. this.client,
  582. new CreateIndexesOperation(
  583. this as TODO_NODE_3286,
  584. this.collectionName,
  585. indexSpecs,
  586. resolveOptions(this, { ...options, maxTimeMS: undefined })
  587. )
  588. );
  589. }
  590. /**
  591. * Drops an index from this collection.
  592. *
  593. * @param indexName - Name of the index to drop.
  594. * @param options - Optional settings for the command
  595. */
  596. async dropIndex(indexName: string, options?: DropIndexesOptions): Promise<Document> {
  597. return executeOperation(
  598. this.client,
  599. new DropIndexOperation(this as TODO_NODE_3286, indexName, {
  600. ...resolveOptions(this, options),
  601. readPreference: ReadPreference.primary
  602. })
  603. );
  604. }
  605. /**
  606. * Drops all indexes from this collection.
  607. *
  608. * @param options - Optional settings for the command
  609. */
  610. async dropIndexes(options?: DropIndexesOptions): Promise<Document> {
  611. return executeOperation(
  612. this.client,
  613. new DropIndexesOperation(this as TODO_NODE_3286, resolveOptions(this, options))
  614. );
  615. }
  616. /**
  617. * Get the list of all indexes information for the collection.
  618. *
  619. * @param options - Optional settings for the command
  620. */
  621. listIndexes(options?: ListIndexesOptions): ListIndexesCursor {
  622. return new ListIndexesCursor(this as TODO_NODE_3286, resolveOptions(this, options));
  623. }
  624. /**
  625. * Checks if one or more indexes exist on the collection, fails on first non-existing index
  626. *
  627. * @param indexes - One or more index names to check.
  628. * @param options - Optional settings for the command
  629. */
  630. async indexExists(
  631. indexes: string | string[],
  632. options?: IndexInformationOptions
  633. ): Promise<boolean> {
  634. return executeOperation(
  635. this.client,
  636. new IndexExistsOperation(this as TODO_NODE_3286, indexes, resolveOptions(this, options))
  637. );
  638. }
  639. /**
  640. * Retrieves this collections index info.
  641. *
  642. * @param options - Optional settings for the command
  643. */
  644. async indexInformation(options?: IndexInformationOptions): Promise<Document> {
  645. return executeOperation(
  646. this.client,
  647. new IndexInformationOperation(this.s.db, this.collectionName, resolveOptions(this, options))
  648. );
  649. }
  650. /**
  651. * Gets an estimate of the count of documents in a collection using collection metadata.
  652. * This will always run a count command on all server versions.
  653. *
  654. * due to an oversight in versions 5.0.0-5.0.8 of MongoDB, the count command,
  655. * which estimatedDocumentCount uses in its implementation, was not included in v1 of
  656. * the Stable API, and so users of the Stable API with estimatedDocumentCount are
  657. * recommended to upgrade their server version to 5.0.9+ or set apiStrict: false to avoid
  658. * encountering errors.
  659. *
  660. * @see {@link https://www.mongodb.com/docs/manual/reference/command/count/#behavior|Count: Behavior}
  661. * @param options - Optional settings for the command
  662. */
  663. async estimatedDocumentCount(options?: EstimatedDocumentCountOptions): Promise<number> {
  664. return executeOperation(
  665. this.client,
  666. new EstimatedDocumentCountOperation(this as TODO_NODE_3286, resolveOptions(this, options))
  667. );
  668. }
  669. /**
  670. * Gets the number of documents matching the filter.
  671. * For a fast count of the total documents in a collection see {@link Collection#estimatedDocumentCount| estimatedDocumentCount}.
  672. * **Note**: When migrating from {@link Collection#count| count} to {@link Collection#countDocuments| countDocuments}
  673. * the following query operators must be replaced:
  674. *
  675. * | Operator | Replacement |
  676. * | -------- | ----------- |
  677. * | `$where` | [`$expr`][1] |
  678. * | `$near` | [`$geoWithin`][2] with [`$center`][3] |
  679. * | `$nearSphere` | [`$geoWithin`][2] with [`$centerSphere`][4] |
  680. *
  681. * [1]: https://www.mongodb.com/docs/manual/reference/operator/query/expr/
  682. * [2]: https://www.mongodb.com/docs/manual/reference/operator/query/geoWithin/
  683. * [3]: https://www.mongodb.com/docs/manual/reference/operator/query/center/#op._S_center
  684. * [4]: https://www.mongodb.com/docs/manual/reference/operator/query/centerSphere/#op._S_centerSphere
  685. *
  686. * @param filter - The filter for the count
  687. * @param options - Optional settings for the command
  688. *
  689. * @see https://www.mongodb.com/docs/manual/reference/operator/query/expr/
  690. * @see https://www.mongodb.com/docs/manual/reference/operator/query/geoWithin/
  691. * @see https://www.mongodb.com/docs/manual/reference/operator/query/center/#op._S_center
  692. * @see https://www.mongodb.com/docs/manual/reference/operator/query/centerSphere/#op._S_centerSphere
  693. */
  694. async countDocuments(
  695. filter: Document = {},
  696. options: CountDocumentsOptions = {}
  697. ): Promise<number> {
  698. return executeOperation(
  699. this.client,
  700. new CountDocumentsOperation(this as TODO_NODE_3286, filter, resolveOptions(this, options))
  701. );
  702. }
  703. /**
  704. * The distinct command returns a list of distinct values for the given key across a collection.
  705. *
  706. * @param key - Field of the document to find distinct values for
  707. * @param filter - The filter for filtering the set of documents to which we apply the distinct filter.
  708. * @param options - Optional settings for the command
  709. */
  710. distinct<Key extends keyof WithId<TSchema>>(
  711. key: Key
  712. ): Promise<Array<Flatten<WithId<TSchema>[Key]>>>;
  713. distinct<Key extends keyof WithId<TSchema>>(
  714. key: Key,
  715. filter: Filter<TSchema>
  716. ): Promise<Array<Flatten<WithId<TSchema>[Key]>>>;
  717. distinct<Key extends keyof WithId<TSchema>>(
  718. key: Key,
  719. filter: Filter<TSchema>,
  720. options: DistinctOptions
  721. ): Promise<Array<Flatten<WithId<TSchema>[Key]>>>;
  722. // Embedded documents overload
  723. distinct(key: string): Promise<any[]>;
  724. distinct(key: string, filter: Filter<TSchema>): Promise<any[]>;
  725. distinct(key: string, filter: Filter<TSchema>, options: DistinctOptions): Promise<any[]>;
  726. async distinct<Key extends keyof WithId<TSchema>>(
  727. key: Key,
  728. filter: Filter<TSchema> = {},
  729. options: DistinctOptions = {}
  730. ): Promise<any[]> {
  731. return executeOperation(
  732. this.client,
  733. new DistinctOperation(
  734. this as TODO_NODE_3286,
  735. key as TODO_NODE_3286,
  736. filter,
  737. resolveOptions(this, options)
  738. )
  739. );
  740. }
  741. /**
  742. * Retrieve all the indexes on the collection.
  743. *
  744. * @param options - Optional settings for the command
  745. */
  746. async indexes(options?: IndexInformationOptions): Promise<Document[]> {
  747. return executeOperation(
  748. this.client,
  749. new IndexesOperation(this as TODO_NODE_3286, resolveOptions(this, options))
  750. );
  751. }
  752. /**
  753. * Get all the collection statistics.
  754. *
  755. * @deprecated the `collStats` operation will be removed in the next major release. Please
  756. * use an aggregation pipeline with the [`$collStats`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/collStats/) stage instead
  757. *
  758. * @param options - Optional settings for the command
  759. */
  760. async stats(options?: CollStatsOptions): Promise<CollStats> {
  761. return executeOperation(
  762. this.client,
  763. new CollStatsOperation(this as TODO_NODE_3286, options) as TODO_NODE_3286
  764. );
  765. }
  766. /**
  767. * Find a document and delete it in one atomic operation. Requires a write lock for the duration of the operation.
  768. *
  769. * @param filter - The filter used to select the document to remove
  770. * @param options - Optional settings for the command
  771. */
  772. async findOneAndDelete(
  773. filter: Filter<TSchema>,
  774. options: FindOneAndDeleteOptions & { includeResultMetadata: true }
  775. ): Promise<ModifyResult<TSchema>>;
  776. async findOneAndDelete(
  777. filter: Filter<TSchema>,
  778. options: FindOneAndDeleteOptions & { includeResultMetadata: false }
  779. ): Promise<WithId<TSchema> | null>;
  780. async findOneAndDelete(
  781. filter: Filter<TSchema>,
  782. options: FindOneAndDeleteOptions
  783. ): Promise<ModifyResult<TSchema>>;
  784. async findOneAndDelete(filter: Filter<TSchema>): Promise<ModifyResult<TSchema>>;
  785. async findOneAndDelete(
  786. filter: Filter<TSchema>,
  787. options?: FindOneAndDeleteOptions
  788. ): Promise<WithId<TSchema> | ModifyResult<TSchema> | null> {
  789. return executeOperation(
  790. this.client,
  791. new FindOneAndDeleteOperation(
  792. this as TODO_NODE_3286,
  793. filter,
  794. resolveOptions(this, options)
  795. ) as TODO_NODE_3286
  796. );
  797. }
  798. /**
  799. * Find a document and replace it in one atomic operation. Requires a write lock for the duration of the operation.
  800. *
  801. * @param filter - The filter used to select the document to replace
  802. * @param replacement - The Document that replaces the matching document
  803. * @param options - Optional settings for the command
  804. */
  805. async findOneAndReplace(
  806. filter: Filter<TSchema>,
  807. replacement: WithoutId<TSchema>,
  808. options: FindOneAndReplaceOptions & { includeResultMetadata: true }
  809. ): Promise<ModifyResult<TSchema>>;
  810. async findOneAndReplace(
  811. filter: Filter<TSchema>,
  812. replacement: WithoutId<TSchema>,
  813. options: FindOneAndReplaceOptions & { includeResultMetadata: false }
  814. ): Promise<WithId<TSchema> | null>;
  815. async findOneAndReplace(
  816. filter: Filter<TSchema>,
  817. replacement: WithoutId<TSchema>,
  818. options: FindOneAndReplaceOptions
  819. ): Promise<ModifyResult<TSchema>>;
  820. async findOneAndReplace(
  821. filter: Filter<TSchema>,
  822. replacement: WithoutId<TSchema>
  823. ): Promise<ModifyResult<TSchema>>;
  824. async findOneAndReplace(
  825. filter: Filter<TSchema>,
  826. replacement: WithoutId<TSchema>,
  827. options?: FindOneAndReplaceOptions
  828. ): Promise<WithId<TSchema> | ModifyResult<TSchema> | null> {
  829. return executeOperation(
  830. this.client,
  831. new FindOneAndReplaceOperation(
  832. this as TODO_NODE_3286,
  833. filter,
  834. replacement,
  835. resolveOptions(this, options)
  836. ) as TODO_NODE_3286
  837. );
  838. }
  839. /**
  840. * Find a document and update it in one atomic operation. Requires a write lock for the duration of the operation.
  841. *
  842. * @param filter - The filter used to select the document to update
  843. * @param update - Update operations to be performed on the document
  844. * @param options - Optional settings for the command
  845. */
  846. async findOneAndUpdate(
  847. filter: Filter<TSchema>,
  848. update: UpdateFilter<TSchema>,
  849. options: FindOneAndUpdateOptions & { includeResultMetadata: true }
  850. ): Promise<ModifyResult<TSchema>>;
  851. async findOneAndUpdate(
  852. filter: Filter<TSchema>,
  853. update: UpdateFilter<TSchema>,
  854. options: FindOneAndUpdateOptions & { includeResultMetadata: false }
  855. ): Promise<WithId<TSchema> | null>;
  856. async findOneAndUpdate(
  857. filter: Filter<TSchema>,
  858. update: UpdateFilter<TSchema>,
  859. options: FindOneAndUpdateOptions
  860. ): Promise<ModifyResult<TSchema>>;
  861. async findOneAndUpdate(
  862. filter: Filter<TSchema>,
  863. update: UpdateFilter<TSchema>
  864. ): Promise<ModifyResult<TSchema>>;
  865. async findOneAndUpdate(
  866. filter: Filter<TSchema>,
  867. update: UpdateFilter<TSchema>,
  868. options?: FindOneAndUpdateOptions
  869. ): Promise<WithId<TSchema> | ModifyResult<TSchema> | null> {
  870. return executeOperation(
  871. this.client,
  872. new FindOneAndUpdateOperation(
  873. this as TODO_NODE_3286,
  874. filter,
  875. update,
  876. resolveOptions(this, options)
  877. ) as TODO_NODE_3286
  878. );
  879. }
  880. /**
  881. * Execute an aggregation framework pipeline against the collection, needs MongoDB \>= 2.2
  882. *
  883. * @param pipeline - An array of aggregation pipelines to execute
  884. * @param options - Optional settings for the command
  885. */
  886. aggregate<T extends Document = Document>(
  887. pipeline: Document[] = [],
  888. options?: AggregateOptions
  889. ): AggregationCursor<T> {
  890. if (!Array.isArray(pipeline)) {
  891. throw new MongoInvalidArgumentError(
  892. 'Argument "pipeline" must be an array of aggregation stages'
  893. );
  894. }
  895. return new AggregationCursor(
  896. this.client,
  897. this.s.namespace,
  898. pipeline,
  899. resolveOptions(this, options)
  900. );
  901. }
  902. /**
  903. * Create a new Change Stream, watching for new changes (insertions, updates, replacements, deletions, and invalidations) in this collection.
  904. *
  905. * @remarks
  906. * watch() accepts two generic arguments for distinct use cases:
  907. * - The first is to override the schema that may be defined for this specific collection
  908. * - The second is to override the shape of the change stream document entirely, if it is not provided the type will default to ChangeStreamDocument of the first argument
  909. * @example
  910. * By just providing the first argument I can type the change to be `ChangeStreamDocument<{ _id: number }>`
  911. * ```ts
  912. * collection.watch<{ _id: number }>()
  913. * .on('change', change => console.log(change._id.toFixed(4)));
  914. * ```
  915. *
  916. * @example
  917. * Passing a second argument provides a way to reflect the type changes caused by an advanced pipeline.
  918. * Here, we are using a pipeline to have MongoDB filter for insert changes only and add a comment.
  919. * No need start from scratch on the ChangeStreamInsertDocument type!
  920. * By using an intersection we can save time and ensure defaults remain the same type!
  921. * ```ts
  922. * collection
  923. * .watch<Schema, ChangeStreamInsertDocument<Schema> & { comment: string }>([
  924. * { $addFields: { comment: 'big changes' } },
  925. * { $match: { operationType: 'insert' } }
  926. * ])
  927. * .on('change', change => {
  928. * change.comment.startsWith('big');
  929. * change.operationType === 'insert';
  930. * // No need to narrow in code because the generics did that for us!
  931. * expectType<Schema>(change.fullDocument);
  932. * });
  933. * ```
  934. *
  935. * @param pipeline - An array of {@link https://www.mongodb.com/docs/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.
  936. * @param options - Optional settings for the command
  937. * @typeParam TLocal - Type of the data being detected by the change stream
  938. * @typeParam TChange - Type of the whole change stream document emitted
  939. */
  940. watch<TLocal extends Document = TSchema, TChange extends Document = ChangeStreamDocument<TLocal>>(
  941. pipeline: Document[] = [],
  942. options: ChangeStreamOptions = {}
  943. ): ChangeStream<TLocal, TChange> {
  944. // Allow optionally not specifying a pipeline
  945. if (!Array.isArray(pipeline)) {
  946. options = pipeline;
  947. pipeline = [];
  948. }
  949. return new ChangeStream<TLocal, TChange>(this, pipeline, resolveOptions(this, options));
  950. }
  951. /**
  952. * Initiate an Out of order batch write operation. All operations will be buffered into insert/update/remove commands executed out of order.
  953. *
  954. * @throws MongoNotConnectedError
  955. * @remarks
  956. * **NOTE:** MongoClient must be connected prior to calling this method due to a known limitation in this legacy implementation.
  957. * However, `collection.bulkWrite()` provides an equivalent API that does not require prior connecting.
  958. */
  959. initializeUnorderedBulkOp(options?: BulkWriteOptions): UnorderedBulkOperation {
  960. return new UnorderedBulkOperation(this as TODO_NODE_3286, resolveOptions(this, options));
  961. }
  962. /**
  963. * Initiate an In order bulk write operation. Operations will be serially executed in the order they are added, creating a new operation for each switch in types.
  964. *
  965. * @throws MongoNotConnectedError
  966. * @remarks
  967. * **NOTE:** MongoClient must be connected prior to calling this method due to a known limitation in this legacy implementation.
  968. * However, `collection.bulkWrite()` provides an equivalent API that does not require prior connecting.
  969. */
  970. initializeOrderedBulkOp(options?: BulkWriteOptions): OrderedBulkOperation {
  971. return new OrderedBulkOperation(this as TODO_NODE_3286, resolveOptions(this, options));
  972. }
  973. /**
  974. * An estimated count of matching documents in the db to a filter.
  975. *
  976. * **NOTE:** This method has been deprecated, since it does not provide an accurate count of the documents
  977. * in a collection. To obtain an accurate count of documents in the collection, use {@link Collection#countDocuments| countDocuments}.
  978. * To obtain an estimated count of all documents in the collection, use {@link Collection#estimatedDocumentCount| estimatedDocumentCount}.
  979. *
  980. * @deprecated use {@link Collection#countDocuments| countDocuments} or {@link Collection#estimatedDocumentCount| estimatedDocumentCount} instead
  981. *
  982. * @param filter - The filter for the count.
  983. * @param options - Optional settings for the command
  984. */
  985. async count(filter: Filter<TSchema> = {}, options: CountOptions = {}): Promise<number> {
  986. return executeOperation(
  987. this.client,
  988. new CountOperation(this.fullNamespace, filter, resolveOptions(this, options))
  989. );
  990. }
  991. /**
  992. * Returns all search indexes for the current collection.
  993. *
  994. * @param options - The options for the list indexes operation.
  995. *
  996. * @remarks Only available when used against a 7.0+ Atlas cluster.
  997. */
  998. listSearchIndexes(options?: ListSearchIndexesOptions): ListSearchIndexesCursor;
  999. /**
  1000. * Returns all search indexes for the current collection.
  1001. *
  1002. * @param name - The name of the index to search for. Only indexes with matching index names will be returned.
  1003. * @param options - The options for the list indexes operation.
  1004. *
  1005. * @remarks Only available when used against a 7.0+ Atlas cluster.
  1006. */
  1007. listSearchIndexes(name: string, options?: ListSearchIndexesOptions): ListSearchIndexesCursor;
  1008. listSearchIndexes(
  1009. indexNameOrOptions?: string | ListSearchIndexesOptions,
  1010. options?: ListSearchIndexesOptions
  1011. ): ListSearchIndexesCursor {
  1012. options =
  1013. typeof indexNameOrOptions === 'object' ? indexNameOrOptions : options == null ? {} : options;
  1014. const indexName =
  1015. indexNameOrOptions == null
  1016. ? null
  1017. : typeof indexNameOrOptions === 'object'
  1018. ? null
  1019. : indexNameOrOptions;
  1020. return new ListSearchIndexesCursor(this as TODO_NODE_3286, indexName, options);
  1021. }
  1022. /**
  1023. * Creates a single search index for the collection.
  1024. *
  1025. * @param description - The index description for the new search index.
  1026. * @returns A promise that resolves to the name of the new search index.
  1027. *
  1028. * @remarks Only available when used against a 7.0+ Atlas cluster.
  1029. */
  1030. async createSearchIndex(description: SearchIndexDescription): Promise<string> {
  1031. const [index] = await this.createSearchIndexes([description]);
  1032. return index;
  1033. }
  1034. /**
  1035. * Creates multiple search indexes for the current collection.
  1036. *
  1037. * @param descriptions - An array of `SearchIndexDescription`s for the new search indexes.
  1038. * @returns A promise that resolves to an array of the newly created search index names.
  1039. *
  1040. * @remarks Only available when used against a 7.0+ Atlas cluster.
  1041. * @returns
  1042. */
  1043. async createSearchIndexes(descriptions: SearchIndexDescription[]): Promise<string[]> {
  1044. return executeOperation(
  1045. this.client,
  1046. new CreateSearchIndexesOperation(this as TODO_NODE_3286, descriptions)
  1047. );
  1048. }
  1049. /**
  1050. * Deletes a search index by index name.
  1051. *
  1052. * @param name - The name of the search index to be deleted.
  1053. *
  1054. * @remarks Only available when used against a 7.0+ Atlas cluster.
  1055. */
  1056. async dropSearchIndex(name: string): Promise<void> {
  1057. return executeOperation(
  1058. this.client,
  1059. new DropSearchIndexOperation(this as TODO_NODE_3286, name)
  1060. );
  1061. }
  1062. /**
  1063. * Updates a search index by replacing the existing index definition with the provided definition.
  1064. *
  1065. * @param name - The name of the search index to update.
  1066. * @param definition - The new search index definition.
  1067. *
  1068. * @remarks Only available when used against a 7.0+ Atlas cluster.
  1069. */
  1070. async updateSearchIndex(name: string, definition: Document): Promise<void> {
  1071. return executeOperation(
  1072. this.client,
  1073. new UpdateSearchIndexOperation(this as TODO_NODE_3286, name, definition)
  1074. );
  1075. }
  1076. }