* A QueryCursor is a concurrency primitive for processing query results * one document at a time. A QueryCursor fulfills the Node.js streams3 API, * in addition to several other mechanisms for loading documents from MongoDB * one at a time. * * QueryCursors execute the model's pre `find` hooks
(query)
| 35 | */ |
| 36 | |
| 37 | function QueryCursor(query) { |
| 38 | // set autoDestroy=true because on node 12 it's by default false |
| 39 | // gh-10902 need autoDestroy to destroy correctly and emit 'close' event |
| 40 | Readable.call(this, { autoDestroy: true, objectMode: true }); |
| 41 | |
| 42 | this.cursor = null; |
| 43 | this.skipped = false; |
| 44 | this.query = query; |
| 45 | const model = query.model; |
| 46 | this._mongooseOptions = {}; |
| 47 | this._transforms = []; |
| 48 | this.model = model; |
| 49 | this.options = {}; |
| 50 | model.hooks.execPre('find', query, (err) => { |
| 51 | if (err != null) { |
| 52 | if (err instanceof kareem.skipWrappedFunction) { |
| 53 | const resultValue = err.args[0]; |
| 54 | if (resultValue != null && (!Array.isArray(resultValue) || resultValue.length)) { |
| 55 | const err = new MongooseError( |
| 56 | 'Cannot `skipMiddlewareFunction()` with a value when using ' + |
| 57 | '`.find().cursor()`, value must be nullish or empty array, got "' + |
| 58 | util.inspect(resultValue) + |
| 59 | '".' |
| 60 | ); |
| 61 | this._markError(err); |
| 62 | this.listeners('error').length > 0 && this.emit('error', err); |
| 63 | return; |
| 64 | } |
| 65 | this.skipped = true; |
| 66 | this.emit('cursor', null); |
| 67 | return; |
| 68 | } |
| 69 | this._markError(err); |
| 70 | this.listeners('error').length > 0 && this.emit('error', err); |
| 71 | return; |
| 72 | } |
| 73 | Object.assign(this.options, query._optionsForExec()); |
| 74 | this._transforms = this._transforms.concat(query._transforms.slice()); |
| 75 | if (this.options.transform) { |
| 76 | this._transforms.push(this.options.transform); |
| 77 | } |
| 78 | // Re: gh-8039, you need to set the `cursor.batchSize` option, top-level |
| 79 | // `batchSize` option doesn't work. |
| 80 | if (this.options.batchSize) { |
| 81 | // Max out the number of documents we'll populate in parallel at 5000. |
| 82 | this.options._populateBatchSize = Math.min(this.options.batchSize, 5000); |
| 83 | } |
| 84 | |
| 85 | if (model.collection._shouldBufferCommands() && model.collection.buffer) { |
| 86 | model.collection.queue.push([ |
| 87 | () => _getRawCursor(query, this) |
| 88 | ]); |
| 89 | } else { |
| 90 | _getRawCursor(query, this); |
| 91 | } |
| 92 | }); |
| 93 | } |
| 94 |
nothing calls this directly
no test coverage detected