123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376 |
- "use strict";
- Object.defineProperty(exports, "__esModule", { value: true });
- exports.FindCursor = exports.FLAGS = void 0;
- const error_1 = require("../error");
- const count_1 = require("../operations/count");
- const execute_operation_1 = require("../operations/execute_operation");
- const find_1 = require("../operations/find");
- const sort_1 = require("../sort");
- const utils_1 = require("../utils");
- const abstract_cursor_1 = require("./abstract_cursor");
- /** @internal */
- const kFilter = Symbol('filter');
- /** @internal */
- const kNumReturned = Symbol('numReturned');
- /** @internal */
- const kBuiltOptions = Symbol('builtOptions');
- /** @public Flags allowed for cursor */
- exports.FLAGS = [
- 'tailable',
- 'oplogReplay',
- 'noCursorTimeout',
- 'awaitData',
- 'exhaust',
- 'partial'
- ];
- /** @public */
- class FindCursor extends abstract_cursor_1.AbstractCursor {
- /** @internal */
- constructor(topology, namespace, filter, options = {}) {
- super(topology, namespace, options);
- this[kFilter] = filter || {};
- this[kBuiltOptions] = options;
- if (options.sort != null) {
- this[kBuiltOptions].sort = (0, sort_1.formatSort)(options.sort);
- }
- }
- clone() {
- const clonedOptions = (0, utils_1.mergeOptions)({}, this[kBuiltOptions]);
- delete clonedOptions.session;
- return new FindCursor(this.topology, this.namespace, this[kFilter], {
- ...clonedOptions
- });
- }
- map(transform) {
- return super.map(transform);
- }
- /** @internal */
- _initialize(session, callback) {
- const findOperation = new find_1.FindOperation(undefined, this.namespace, this[kFilter], {
- ...this[kBuiltOptions],
- ...this.cursorOptions,
- session
- });
- (0, execute_operation_1.executeOperation)(this.topology, findOperation, (err, response) => {
- if (err || response == null)
- return callback(err);
- // TODO: We only need this for legacy queries that do not support `limit`, maybe
- // the value should only be saved in those cases.
- if (response.cursor) {
- this[kNumReturned] = response.cursor.firstBatch.length;
- }
- else {
- this[kNumReturned] = response.documents ? response.documents.length : 0;
- }
- // TODO: NODE-2882
- callback(undefined, { server: findOperation.server, session, response });
- });
- }
- /** @internal */
- _getMore(batchSize, callback) {
- // NOTE: this is to support client provided limits in pre-command servers
- const numReturned = this[kNumReturned];
- if (numReturned) {
- const limit = this[kBuiltOptions].limit;
- batchSize =
- limit && limit > 0 && numReturned + batchSize > limit ? limit - numReturned : batchSize;
- if (batchSize <= 0) {
- return this.close(callback);
- }
- }
- super._getMore(batchSize, (err, response) => {
- if (err)
- return callback(err);
- // TODO: wrap this in some logic to prevent it from happening if we don't need this support
- if (response) {
- this[kNumReturned] = this[kNumReturned] + response.cursor.nextBatch.length;
- }
- callback(undefined, response);
- });
- }
- count(options, callback) {
- if (typeof options === 'boolean') {
- throw new error_1.MongoInvalidArgumentError('Invalid first parameter to count');
- }
- if (typeof options === 'function')
- (callback = options), (options = {});
- options = options !== null && options !== void 0 ? options : {};
- return (0, execute_operation_1.executeOperation)(this.topology, new count_1.CountOperation(this.namespace, this[kFilter], {
- ...this[kBuiltOptions],
- ...this.cursorOptions,
- ...options
- }), callback);
- }
- explain(verbosity, callback) {
- if (typeof verbosity === 'function')
- (callback = verbosity), (verbosity = true);
- if (verbosity == null)
- verbosity = true;
- return (0, execute_operation_1.executeOperation)(this.topology, new find_1.FindOperation(undefined, this.namespace, this[kFilter], {
- ...this[kBuiltOptions],
- ...this.cursorOptions,
- explain: verbosity
- }), callback);
- }
- /** Set the cursor query */
- filter(filter) {
- (0, abstract_cursor_1.assertUninitialized)(this);
- this[kFilter] = filter;
- return this;
- }
- /**
- * Set the cursor hint
- *
- * @param hint - If specified, then the query system will only consider plans using the hinted index.
- */
- hint(hint) {
- (0, abstract_cursor_1.assertUninitialized)(this);
- this[kBuiltOptions].hint = hint;
- return this;
- }
- /**
- * Set the cursor min
- *
- * @param min - Specify a $min value to specify the inclusive lower bound for a specific index in order to constrain the results of find(). The $min specifies the lower bound for all keys of a specific index in order.
- */
- min(min) {
- (0, abstract_cursor_1.assertUninitialized)(this);
- this[kBuiltOptions].min = min;
- return this;
- }
- /**
- * Set the cursor max
- *
- * @param max - Specify a $max value to specify the exclusive upper bound for a specific index in order to constrain the results of find(). The $max specifies the upper bound for all keys of a specific index in order.
- */
- max(max) {
- (0, abstract_cursor_1.assertUninitialized)(this);
- this[kBuiltOptions].max = max;
- return this;
- }
- /**
- * Set the cursor returnKey.
- * If set to true, modifies the cursor to only return the index field or fields for the results of the query, rather than documents.
- * If set to true and the query does not use an index to perform the read operation, the returned documents will not contain any fields.
- *
- * @param value - the returnKey value.
- */
- returnKey(value) {
- (0, abstract_cursor_1.assertUninitialized)(this);
- this[kBuiltOptions].returnKey = value;
- return this;
- }
- /**
- * Modifies the output of a query by adding a field $recordId to matching documents. $recordId is the internal key which uniquely identifies a document in a collection.
- *
- * @param value - The $showDiskLoc option has now been deprecated and replaced with the showRecordId field. $showDiskLoc will still be accepted for OP_QUERY stye find.
- */
- showRecordId(value) {
- (0, abstract_cursor_1.assertUninitialized)(this);
- this[kBuiltOptions].showRecordId = value;
- return this;
- }
- /**
- * Add a query modifier to the cursor query
- *
- * @param name - The query modifier (must start with $, such as $orderby etc)
- * @param value - The modifier value.
- */
- addQueryModifier(name, value) {
- (0, abstract_cursor_1.assertUninitialized)(this);
- if (name[0] !== '$') {
- throw new error_1.MongoInvalidArgumentError(`${name} is not a valid query modifier`);
- }
- // Strip of the $
- const field = name.substr(1);
- // NOTE: consider some TS magic for this
- switch (field) {
- case 'comment':
- this[kBuiltOptions].comment = value;
- break;
- case 'explain':
- this[kBuiltOptions].explain = value;
- break;
- case 'hint':
- this[kBuiltOptions].hint = value;
- break;
- case 'max':
- this[kBuiltOptions].max = value;
- break;
- case 'maxTimeMS':
- this[kBuiltOptions].maxTimeMS = value;
- break;
- case 'min':
- this[kBuiltOptions].min = value;
- break;
- case 'orderby':
- this[kBuiltOptions].sort = (0, sort_1.formatSort)(value);
- break;
- case 'query':
- this[kFilter] = value;
- break;
- case 'returnKey':
- this[kBuiltOptions].returnKey = value;
- break;
- case 'showDiskLoc':
- this[kBuiltOptions].showRecordId = value;
- break;
- default:
- throw new error_1.MongoInvalidArgumentError(`Invalid query modifier: ${name}`);
- }
- return this;
- }
- /**
- * Add a comment to the cursor query allowing for tracking the comment in the log.
- *
- * @param value - The comment attached to this query.
- */
- comment(value) {
- (0, abstract_cursor_1.assertUninitialized)(this);
- this[kBuiltOptions].comment = value;
- return this;
- }
- /**
- * Set a maxAwaitTimeMS on a tailing cursor query to allow to customize the timeout value for the option awaitData (Only supported on MongoDB 3.2 or higher, ignored otherwise)
- *
- * @param value - Number of milliseconds to wait before aborting the tailed query.
- */
- maxAwaitTimeMS(value) {
- (0, abstract_cursor_1.assertUninitialized)(this);
- if (typeof value !== 'number') {
- throw new error_1.MongoInvalidArgumentError('Argument for maxAwaitTimeMS must be a number');
- }
- this[kBuiltOptions].maxAwaitTimeMS = value;
- return this;
- }
- /**
- * Set a maxTimeMS on the cursor query, allowing for hard timeout limits on queries (Only supported on MongoDB 2.6 or higher)
- *
- * @param value - Number of milliseconds to wait before aborting the query.
- */
- maxTimeMS(value) {
- (0, abstract_cursor_1.assertUninitialized)(this);
- if (typeof value !== 'number') {
- throw new error_1.MongoInvalidArgumentError('Argument for maxTimeMS must be a number');
- }
- this[kBuiltOptions].maxTimeMS = value;
- return this;
- }
- /**
- * Add a project stage to the aggregation pipeline
- *
- * @remarks
- * In order to strictly type this function you must provide an interface
- * that represents the effect of your projection on the result documents.
- *
- * By default chaining a projection to your cursor changes the returned type to the generic
- * {@link Document} type.
- * You should specify a parameterized type to have assertions on your final results.
- *
- * @example
- * ```typescript
- * // Best way
- * const docs: FindCursor<{ a: number }> = cursor.project<{ a: number }>({ _id: 0, a: true });
- * // Flexible way
- * const docs: FindCursor<Document> = cursor.project({ _id: 0, a: true });
- * ```
- *
- * @remarks
- *
- * **Note for Typescript Users:** adding a transform changes the return type of the iteration of this cursor,
- * it **does not** return a new instance of a cursor. This means when calling project,
- * you should always assign the result to a new variable in order to get a correctly typed cursor variable.
- * Take note of the following example:
- *
- * @example
- * ```typescript
- * const cursor: FindCursor<{ a: number; b: string }> = coll.find();
- * const projectCursor = cursor.project<{ a: number }>({ _id: 0, a: true });
- * const aPropOnlyArray: {a: number}[] = await projectCursor.toArray();
- *
- * // or always use chaining and save the final cursor
- *
- * const cursor = coll.find().project<{ a: string }>({
- * _id: 0,
- * a: { $convert: { input: '$a', to: 'string' }
- * }});
- * ```
- */
- project(value) {
- (0, abstract_cursor_1.assertUninitialized)(this);
- this[kBuiltOptions].projection = value;
- return this;
- }
- /**
- * Sets the sort order of the cursor query.
- *
- * @param sort - The key or keys set for the sort.
- * @param direction - The direction of the sorting (1 or -1).
- */
- sort(sort, direction) {
- (0, abstract_cursor_1.assertUninitialized)(this);
- if (this[kBuiltOptions].tailable) {
- throw new error_1.MongoTailableCursorError('Tailable cursor does not support sorting');
- }
- this[kBuiltOptions].sort = (0, sort_1.formatSort)(sort, direction);
- return this;
- }
- /**
- * Allows disk use for blocking sort operations exceeding 100MB memory. (MongoDB 3.2 or higher)
- *
- * @remarks
- * {@link https://docs.mongodb.com/manual/reference/command/find/#find-cmd-allowdiskuse | find command allowDiskUse documentation}
- */
- allowDiskUse() {
- (0, abstract_cursor_1.assertUninitialized)(this);
- if (!this[kBuiltOptions].sort) {
- throw new error_1.MongoInvalidArgumentError('Option "allowDiskUse" requires a sort specification');
- }
- this[kBuiltOptions].allowDiskUse = true;
- return this;
- }
- /**
- * Set the collation options for the cursor.
- *
- * @param value - The cursor collation options (MongoDB 3.4 or higher) settings for update operation (see 3.4 documentation for available fields).
- */
- collation(value) {
- (0, abstract_cursor_1.assertUninitialized)(this);
- this[kBuiltOptions].collation = value;
- return this;
- }
- /**
- * Set the limit for the cursor.
- *
- * @param value - The limit for the cursor query.
- */
- limit(value) {
- (0, abstract_cursor_1.assertUninitialized)(this);
- if (this[kBuiltOptions].tailable) {
- throw new error_1.MongoTailableCursorError('Tailable cursor does not support limit');
- }
- if (typeof value !== 'number') {
- throw new error_1.MongoInvalidArgumentError('Operation "limit" requires an integer');
- }
- this[kBuiltOptions].limit = value;
- return this;
- }
- /**
- * Set the skip for the cursor.
- *
- * @param value - The skip for the cursor query.
- */
- skip(value) {
- (0, abstract_cursor_1.assertUninitialized)(this);
- if (this[kBuiltOptions].tailable) {
- throw new error_1.MongoTailableCursorError('Tailable cursor does not support skip');
- }
- if (typeof value !== 'number') {
- throw new error_1.MongoInvalidArgumentError('Operation "skip" requires an integer');
- }
- this[kBuiltOptions].skip = value;
- return this;
- }
- }
- exports.FindCursor = FindCursor;
- //# sourceMappingURL=find_cursor.js.map
|