UNPKG

10.6 kBJavaScriptView Raw
1'use strict';
2
3const MongoError = require('./core').MongoError;
4const Cursor = require('./cursor');
5const CursorState = require('./core/cursor').CursorState;
6const deprecate = require('util').deprecate;
7
8/**
9 * @fileOverview The **AggregationCursor** class is an internal class that embodies an aggregation cursor on MongoDB
10 * allowing for iteration over the results returned from the underlying query. It supports
11 * one by one document iteration, conversion to an array or can be iterated as a Node 4.X
12 * or higher stream
13 *
14 * **AGGREGATIONCURSOR Cannot directly be instantiated**
15 * @example
16 * const MongoClient = require('mongodb').MongoClient;
17 * const test = require('assert');
18 * // Connection url
19 * const url = 'mongodb://localhost:27017';
20 * // Database Name
21 * const dbName = 'test';
22 * // Connect using MongoClient
23 * MongoClient.connect(url, function(err, client) {
24 * // Create a collection we want to drop later
25 * const col = client.db(dbName).collection('createIndexExample1');
26 * // Insert a bunch of documents
27 * col.insert([{a:1, b:1}
28 * , {a:2, b:2}, {a:3, b:3}
29 * , {a:4, b:4}], {w:1}, function(err, result) {
30 * test.equal(null, err);
31 * // Show that duplicate records got dropped
32 * col.aggregation({}, {cursor: {}}).toArray(function(err, items) {
33 * test.equal(null, err);
34 * test.equal(4, items.length);
35 * client.close();
36 * });
37 * });
38 * });
39 */
40
41/**
42 * Namespace provided by the browser.
43 * @external Readable
44 */
45
46/**
47 * Creates a new Aggregation Cursor instance (INTERNAL TYPE, do not instantiate directly)
48 * @class AggregationCursor
49 * @extends external:Readable
50 * @fires AggregationCursor#data
51 * @fires AggregationCursor#end
52 * @fires AggregationCursor#close
53 * @fires AggregationCursor#readable
54 * @return {AggregationCursor} an AggregationCursor instance.
55 */
56class AggregationCursor extends Cursor {
57 constructor(topology, operation, options) {
58 super(topology, operation, options);
59 }
60
61 /**
62 * Set the batch size for the cursor.
63 * @method
64 * @param {number} value The number of documents to return per batch. See {@link https://docs.mongodb.com/manual/reference/command/aggregate|aggregation documentation}.
65 * @throws {MongoError}
66 * @return {AggregationCursor}
67 */
68 batchSize(value) {
69 if (this.s.state === CursorState.CLOSED || this.isDead()) {
70 throw MongoError.create({ message: 'Cursor is closed', driver: true });
71 }
72
73 if (typeof value !== 'number') {
74 throw MongoError.create({ message: 'batchSize requires an integer', driver: true });
75 }
76
77 this.operation.options.batchSize = value;
78 this.setCursorBatchSize(value);
79 return this;
80 }
81
82 /**
83 * Add a geoNear stage to the aggregation pipeline
84 * @method
85 * @param {object} document The geoNear stage document.
86 * @return {AggregationCursor}
87 */
88 geoNear(document) {
89 this.operation.addToPipeline({ $geoNear: document });
90 return this;
91 }
92
93 /**
94 * Add a group stage to the aggregation pipeline
95 * @method
96 * @param {object} document The group stage document.
97 * @return {AggregationCursor}
98 */
99 group(document) {
100 this.operation.addToPipeline({ $group: document });
101 return this;
102 }
103
104 /**
105 * Add a limit stage to the aggregation pipeline
106 * @method
107 * @param {number} value The state limit value.
108 * @return {AggregationCursor}
109 */
110 limit(value) {
111 this.operation.addToPipeline({ $limit: value });
112 return this;
113 }
114
115 /**
116 * Add a match stage to the aggregation pipeline
117 * @method
118 * @param {object} document The match stage document.
119 * @return {AggregationCursor}
120 */
121 match(document) {
122 this.operation.addToPipeline({ $match: document });
123 return this;
124 }
125
126 /**
127 * Add a maxTimeMS stage to the aggregation pipeline
128 * @method
129 * @param {number} value The state maxTimeMS value.
130 * @return {AggregationCursor}
131 */
132 maxTimeMS(value) {
133 this.operation.options.maxTimeMS = value;
134 return this;
135 }
136
137 /**
138 * Add a out stage to the aggregation pipeline
139 * @method
140 * @param {number} destination The destination name.
141 * @return {AggregationCursor}
142 */
143 out(destination) {
144 this.operation.addToPipeline({ $out: destination });
145 return this;
146 }
147
148 /**
149 * Add a project stage to the aggregation pipeline
150 * @method
151 * @param {object} document The project stage document.
152 * @return {AggregationCursor}
153 */
154 project(document) {
155 this.operation.addToPipeline({ $project: document });
156 return this;
157 }
158
159 /**
160 * Add a lookup stage to the aggregation pipeline
161 * @method
162 * @param {object} document The lookup stage document.
163 * @return {AggregationCursor}
164 */
165 lookup(document) {
166 this.operation.addToPipeline({ $lookup: document });
167 return this;
168 }
169
170 /**
171 * Add a redact stage to the aggregation pipeline
172 * @method
173 * @param {object} document The redact stage document.
174 * @return {AggregationCursor}
175 */
176 redact(document) {
177 this.operation.addToPipeline({ $redact: document });
178 return this;
179 }
180
181 /**
182 * Add a skip stage to the aggregation pipeline
183 * @method
184 * @param {number} value The state skip value.
185 * @return {AggregationCursor}
186 */
187 skip(value) {
188 this.operation.addToPipeline({ $skip: value });
189 return this;
190 }
191
192 /**
193 * Add a sort stage to the aggregation pipeline
194 * @method
195 * @param {object} document The sort stage document.
196 * @return {AggregationCursor}
197 */
198 sort(document) {
199 this.operation.addToPipeline({ $sort: document });
200 return this;
201 }
202
203 /**
204 * Add a unwind stage to the aggregation pipeline
205 * @method
206 * @param {number} field The unwind field name.
207 * @return {AggregationCursor}
208 */
209 unwind(field) {
210 this.operation.addToPipeline({ $unwind: field });
211 return this;
212 }
213
214 /**
215 * Return the cursor logger
216 * @method
217 * @return {Logger} return the cursor logger
218 * @ignore
219 */
220 getLogger() {
221 return this.logger;
222 }
223}
224
225// aliases
226AggregationCursor.prototype.get = AggregationCursor.prototype.toArray;
227
228// deprecated methods
229deprecate(
230 AggregationCursor.prototype.geoNear,
231 'The `$geoNear` stage is deprecated in MongoDB 4.0, and removed in version 4.2.'
232);
233
234/**
235 * AggregationCursor stream data event, fired for each document in the cursor.
236 *
237 * @event AggregationCursor#data
238 * @type {object}
239 */
240
241/**
242 * AggregationCursor stream end event
243 *
244 * @event AggregationCursor#end
245 * @type {null}
246 */
247
248/**
249 * AggregationCursor stream close event
250 *
251 * @event AggregationCursor#close
252 * @type {null}
253 */
254
255/**
256 * AggregationCursor stream readable event
257 *
258 * @event AggregationCursor#readable
259 * @type {null}
260 */
261
262/**
263 * Get the next available document from the cursor, returns null if no more documents are available.
264 * @function AggregationCursor.prototype.next
265 * @param {AggregationCursor~resultCallback} [callback] The result callback.
266 * @throws {MongoError}
267 * @return {Promise} returns Promise if no callback passed
268 */
269
270/**
271 * Check if there is any document still available in the cursor
272 * @function AggregationCursor.prototype.hasNext
273 * @param {AggregationCursor~resultCallback} [callback] The result callback.
274 * @throws {MongoError}
275 * @return {Promise} returns Promise if no callback passed
276 */
277
278/**
279 * The callback format for results
280 * @callback AggregationCursor~toArrayResultCallback
281 * @param {MongoError} error An error instance representing the error during the execution.
282 * @param {object[]} documents All the documents the satisfy the cursor.
283 */
284
285/**
286 * Returns an array of documents. The caller is responsible for making sure that there
287 * is enough memory to store the results. Note that the array only contain partial
288 * results when this cursor had been previously accessed. In that case,
289 * cursor.rewind() can be used to reset the cursor.
290 * @method AggregationCursor.prototype.toArray
291 * @param {AggregationCursor~toArrayResultCallback} [callback] The result callback.
292 * @throws {MongoError}
293 * @return {Promise} returns Promise if no callback passed
294 */
295
296/**
297 * The callback format for results
298 * @callback AggregationCursor~resultCallback
299 * @param {MongoError} error An error instance representing the error during the execution.
300 * @param {(object|null)} result The result object if the command was executed successfully.
301 */
302
303/**
304 * Iterates over all the documents for this cursor. As with **{cursor.toArray}**,
305 * not all of the elements will be iterated if this cursor had been previously accessed.
306 * In that case, **{cursor.rewind}** can be used to reset the cursor. However, unlike
307 * **{cursor.toArray}**, the cursor will only hold a maximum of batch size elements
308 * at any given time if batch size is specified. Otherwise, the caller is responsible
309 * for making sure that the entire result can fit the memory.
310 * @method AggregationCursor.prototype.each
311 * @deprecated
312 * @param {AggregationCursor~resultCallback} callback The result callback.
313 * @throws {MongoError}
314 * @return {null}
315 */
316
317/**
318 * Close the cursor, sending a AggregationCursor command and emitting close.
319 * @method AggregationCursor.prototype.close
320 * @param {AggregationCursor~resultCallback} [callback] The result callback.
321 * @return {Promise} returns Promise if no callback passed
322 */
323
324/**
325 * Is the cursor closed
326 * @method AggregationCursor.prototype.isClosed
327 * @return {boolean}
328 */
329
330/**
331 * Execute the explain for the cursor
332 * @method AggregationCursor.prototype.explain
333 * @param {AggregationCursor~resultCallback} [callback] The result callback.
334 * @return {Promise} returns Promise if no callback passed
335 */
336
337/**
338 * Clone the cursor
339 * @function AggregationCursor.prototype.clone
340 * @return {AggregationCursor}
341 */
342
343/**
344 * Resets the cursor
345 * @function AggregationCursor.prototype.rewind
346 * @return {AggregationCursor}
347 */
348
349/**
350 * The callback format for the forEach iterator method
351 * @callback AggregationCursor~iteratorCallback
352 * @param {Object} doc An emitted document for the iterator
353 */
354
355/**
356 * The callback error format for the forEach iterator method
357 * @callback AggregationCursor~endCallback
358 * @param {MongoError} error An error instance representing the error during the execution.
359 */
360
361/**
362 * Iterates over all the documents for this cursor using the iterator, callback pattern.
363 * @method AggregationCursor.prototype.forEach
364 * @param {AggregationCursor~iteratorCallback} iterator The iteration callback.
365 * @param {AggregationCursor~endCallback} callback The end callback.
366 * @throws {MongoError}
367 * @return {null}
368 */
369
370module.exports = AggregationCursor;