0
# Query and Cursor Management
1
2
Cursor operations for iterating through query results with automatic connection handling.
3
4
## Capabilities
5
6
### Cursor Creation
7
8
Cursors are created by find operations and provide methods for iterating through results.
9
10
```javascript { .api }
11
/**
12
* Create cursor from collection find operation
13
* @param {object} [query] - Query selector
14
* @param {object} [options] - Query options
15
* @returns {SkinCursor} Cursor instance
16
*/
17
collection.find(query, options); // Returns cursor when no callback provided
18
```
19
20
### Result Retrieval
21
22
Methods for retrieving query results from cursors.
23
24
```javascript { .api }
25
/**
26
* Convert cursor to array of documents
27
* @param {function} callback - Callback function (err, docs)
28
* @returns {void}
29
*/
30
toArray(callback);
31
32
/**
33
* Iterate through cursor documents one by one
34
* @param {function} callback - Callback function (err, doc)
35
* @returns {void}
36
*/
37
each(callback);
38
39
/**
40
* Get next document from cursor
41
* @param {function} callback - Callback function (err, doc)
42
* @returns {void}
43
*/
44
next(callback);
45
46
/**
47
* Get count of documents matching cursor query
48
* @param {boolean} [applySkipLimit] - Whether to apply skip/limit
49
* @param {function} callback - Callback function (err, count)
50
* @returns {void}
51
*/
52
count(applySkipLimit, callback);
53
```
54
55
**Usage Examples:**
56
57
```javascript
58
const mongoskin = require('mongoskin');
59
const db = mongoskin.db('mongodb://localhost:27017/myapp');
60
const users = db.collection('users');
61
62
// Get all results as array
63
const cursor = users.find({ active: true });
64
cursor.toArray((err, docs) => {
65
if (err) throw err;
66
console.log('Found', docs.length, 'active users');
67
docs.forEach(user => console.log(user.name));
68
});
69
70
// Iterate through results one by one
71
users.find({ role: 'admin' }).each((err, admin) => {
72
if (err) throw err;
73
if (admin) {
74
console.log('Admin user:', admin.name);
75
} else {
76
console.log('No more admin users');
77
}
78
});
79
80
// Get next document
81
const adminCursor = users.find({ role: 'admin' });
82
adminCursor.next((err, admin) => {
83
if (err) throw err;
84
if (admin) {
85
console.log('First admin:', admin.name);
86
}
87
});
88
89
// Count matching documents
90
users.find({ active: true }).count((err, count) => {
91
if (err) throw err;
92
console.log('Total active users:', count);
93
});
94
```
95
96
### Cursor Modifiers
97
98
Methods for modifying cursor behavior before executing queries.
99
100
```javascript { .api }
101
/**
102
* Limit number of documents returned
103
* @param {number} limit - Maximum number of documents
104
* @returns {SkinCursor} this
105
*/
106
limit(limit);
107
108
/**
109
* Skip number of documents
110
* @param {number} skip - Number of documents to skip
111
* @returns {SkinCursor} this
112
*/
113
skip(skip);
114
115
/**
116
* Sort documents by specified fields
117
* @param {object} sort - Sort specification object
118
* @returns {SkinCursor} this
119
*/
120
sort(sort);
121
122
/**
123
* Set read preference for cursor
124
* @param {string} preference - Read preference
125
* @returns {SkinCursor} this
126
*/
127
setReadPreference(preference);
128
```
129
130
**Usage Examples:**
131
132
```javascript
133
const users = db.collection('users');
134
135
// Pagination with limit and skip
136
users.find({ active: true })
137
.skip(20)
138
.limit(10)
139
.sort({ name: 1 })
140
.toArray((err, page) => {
141
if (err) throw err;
142
console.log('Page 3 users:', page);
143
});
144
145
// Complex sorting
146
users.find({ role: 'user' })
147
.sort({ lastLogin: -1, name: 1 })
148
.limit(5)
149
.toArray((err, recentUsers) => {
150
if (err) throw err;
151
console.log('Most recently active users:', recentUsers);
152
});
153
154
// Read preference for replica sets
155
users.find({ department: 'engineering' })
156
.setReadPreference('secondary')
157
.toArray((err, engineers) => {
158
if (err) throw err;
159
console.log('Engineers from secondary:', engineers);
160
});
161
```
162
163
### Stream Interface
164
165
Stream-based cursor operations for handling large result sets.
166
167
```javascript { .api }
168
/**
169
* Convert cursor to readable stream
170
* @param {object} [options] - Stream options
171
* @returns {Stream} Readable stream of documents
172
*/
173
stream(options);
174
175
/**
176
* Transform cursor results through transform stream
177
* @param {function} transform - Transform function
178
* @param {object} [options] - Transform options
179
* @returns {Stream} Transform stream
180
*/
181
pipe(transform, options);
182
```
183
184
**Usage Examples:**
185
186
```javascript
187
const users = db.collection('users');
188
189
// Stream large result set
190
const userStream = users.find({ active: true }).stream();
191
192
userStream.on('data', (user) => {
193
console.log('Processing user:', user.name);
194
// Process user without loading all into memory
195
});
196
197
userStream.on('end', () => {
198
console.log('Finished processing all users');
199
});
200
201
userStream.on('error', (err) => {
202
console.error('Stream error:', err);
203
});
204
205
// Transform stream example (if supported)
206
const fs = require('fs');
207
const transform = require('stream').Transform;
208
209
const csvTransform = new transform({
210
objectMode: true,
211
transform(user, encoding, callback) {
212
const csv = `${user.name},${user.email},${user.role}\n`;
213
callback(null, csv);
214
}
215
});
216
217
users.find({})
218
.stream()
219
.pipe(csvTransform)
220
.pipe(fs.createWriteStream('users.csv'));
221
```
222
223
### Query Explanation
224
225
Methods for analyzing query performance and execution plans.
226
227
```javascript { .api }
228
/**
229
* Explain query execution plan
230
* @param {function} callback - Callback function (err, explanation)
231
* @returns {void}
232
*/
233
explain(callback);
234
235
/**
236
* Get query hint for index usage
237
* @param {object} hint - Index hint object
238
* @returns {SkinCursor} this
239
*/
240
hint(hint);
241
```
242
243
**Usage Examples:**
244
245
```javascript
246
const users = db.collection('users');
247
248
// Explain query execution
249
users.find({ email: 'user@example.com' })
250
.explain((err, explanation) => {
251
if (err) throw err;
252
console.log('Query explanation:', explanation);
253
});
254
255
// Force index usage with hint
256
users.find({ name: 'John' })
257
.hint({ name: 1 })
258
.toArray((err, johns) => {
259
if (err) throw err;
260
console.log('Johns found using name index:', johns);
261
});
262
```
263
264
### Cursor State Management
265
266
Methods for checking and managing cursor state.
267
268
```javascript { .api }
269
/**
270
* Check if cursor is closed
271
* @returns {boolean} true if cursor is closed
272
*/
273
isClosed();
274
275
/**
276
* Close cursor manually
277
* @param {function} [callback] - Optional callback function
278
* @returns {void}
279
*/
280
close(callback);
281
282
/**
283
* Rewind cursor to beginning
284
* @returns {SkinCursor} this
285
*/
286
rewind();
287
```
288
289
**Usage Examples:**
290
291
```javascript
292
const users = db.collection('users');
293
const cursor = users.find({ active: true });
294
295
// Check cursor state
296
console.log('Cursor closed?', cursor.isClosed());
297
298
// Process some documents
299
cursor.next((err, user) => {
300
if (err) throw err;
301
console.log('First user:', user);
302
303
// Rewind to start over
304
cursor.rewind();
305
306
// Close cursor when done
307
cursor.close((err) => {
308
if (err) throw err;
309
console.log('Cursor closed');
310
});
311
});
312
```
313
314
### Advanced Cursor Options
315
316
Advanced cursor configuration options for fine-tuning query behavior.
317
318
```javascript { .api }
319
/**
320
* Set batch size for cursor operations
321
* @param {number} size - Batch size
322
* @returns {SkinCursor} this
323
*/
324
batchSize(size);
325
326
/**
327
* Set maximum time cursor can run
328
* @param {number} ms - Maximum time in milliseconds
329
* @returns {SkinCursor} this
330
*/
331
maxTimeMS(ms);
332
333
/**
334
* Enable tailable cursor for capped collections
335
* @param {boolean} [tail] - Enable tailable cursor
336
* @returns {SkinCursor} this
337
*/
338
tailable(tail);
339
340
/**
341
* Return partial results if some shards are down
342
* @param {boolean} [partial] - Allow partial results
343
* @returns {SkinCursor} this
344
*/
345
partial(partial);
346
```
347
348
**Usage Examples:**
349
350
```javascript
351
const logs = db.collection('logs'); // capped collection
352
353
// Tailable cursor for real-time log monitoring
354
logs.find({})
355
.tailable(true)
356
.each((err, log) => {
357
if (err) throw err;
358
if (log) {
359
console.log('New log entry:', log.message);
360
}
361
});
362
363
// Optimized cursor with batch size
364
users.find({ active: true })
365
.batchSize(100)
366
.maxTimeMS(5000)
367
.toArray((err, users) => {
368
if (err) throw err;
369
console.log('Retrieved users with optimized cursor');
370
});
371
372
// Partial results from sharded collection
373
const shardedCollection = db.collection('sharded_data');
374
shardedCollection.find({})
375
.partial(true)
376
.toArray((err, results) => {
377
if (err) throw err;
378
console.log('Partial results:', results.length);
379
});
380
```