# Cursors

## QueryCursor

Cursor defaults are access(1), batchSize(100), grant(null), maxTimeMs(2000), skipAcl(false).

access(level)\
batchSize(sz)\
close()\
count()\
expand(...props)\
forEach(fn)\
grant(level = null)\
hasNext()\
include(...props)\
isClosed()\
limit(count)\
locale(identifier)\
map(fn)\
maxTimeMS(ms)\
next()\
passthru()\
pathPrefix(path = null)\
pathRead(path, options)\
paths(...props)\
reduce(fn, memo)\
skip(count)\
skipAcl(bool = true)\
sort(object)\
stream(fnEach, fnMap)\
where(filter)\
toArray()\
toList()

```
return org.objects.account
  .find()
  .skipAcl()
  .grant(consts.accessLevels.read)
  .paths('_id', 'name.first')
  .sort({'name.first': 1})
  .limit(50)
  .toList() // use paging with hasMore
```

### QueryCursor.access(level)

Sets the minimum context access level the caller needs to return results. To return only results to which the caller has update access, for example, call `cursor.access(consts.accessLevels.update)`.

**Arguments**

* `level` (Number)

**Returns**

this

### QueryCursor.batchSize(sz)

Sets the internal cursor batch size for fetching results. Normally, the default is optimal but in cases where a large number of very small documents is being fetched, a larger batch size may be slightly more performant.

**Arguments**

* `sz` (Number) The internal cursor batch size (between 1 and 1000).

**Returns**

this

### QueryCursor.close()

Releases the cursor resources. It's not necessary to close cursors as this is done automatically when a script ends or is exhausted, but in some cases a script may need to free up a cursor mid-stream in order to open up another one.

**Returns**

this

### QueryCursor.count()

Executes a count using the current match filter and cursor options.

**Returns**

Number the number of matched documents.

### QueryCursor.expand(...props)

Sets the references that should be expanded in the returned documents. Reference properties can also be selectively retrieved using the paths option.

**Arguments**

* `...props` (String) Property paths to expand.

**Returns**

this

### QueryCursor.forEach(fn)

Executes the cursor, calling `fn` with each document.

**Arguments**

* `fn` (Function) a function to call for each element in the form of `(document) => {}`.

**Returns**

undefined

### QueryCursor.grant(level = null)

Sets the property grant level for the operation.

**Arguments**

* `level` (Number)

**Returns**

this

### QueryCursor.hasNext()

Executes the cursor, returning true if `next()` can be safely called to fetch the next result.

**Returns**

bool

### QueryCursor.include(...props)

Sets the optional properties to include in results. Optional properties can also be explicitly retrieved using the paths option. Some properties are marked as optional, meaning they are not included in results by default (e.g. certain List properties).

**Arguments**

* `...props` (String) Property paths to include (e.g. `include('connections')`);

**Returns**

this

### QueryCursor.isClosed()

Returns true if a cursor has been opened and has been subsequently closed or exhausted.

**Returns**

Boolean

### QueryCursor.limit(count)

Limits the number of query results to `count`. By default, the script `toList()` limit is 10, though cursors have no default limit.

**Arguments**

* `count` (Number) The limit.

**Returns**

this

### QueryCursor.locale(identifier)

Specifies the locale of the cursor for any localized strings.

**Arguments**

* `identifier` (String) The locale identifier, which consists of a 2 or 3 letter language tag optionally followed by a region separated by `_`. For example, `en`, `en_US`, `en_UK`, etc.

**Returns**

this

### QueryCursor.map(fn)

Exhausts the cursor, calling `fn` with each document, and returning an array of results. Because `map()` iterates through the cursor, the caller should set a sane `limit()`.

**Arguments**

* `fn` (Function) a function to call for each result in the form of `(document) => { return document; }`.

**Returns**

Object\[]

### QueryCursor.maxTimeMs(ms)

Set the maximum time a query is allowed to run.

**Arguments**

* `ms` (Number) A number between 10 and 10000.

**Returns**

this

### QueryCursor.next()

Returns the next result. Throws a RangeError is there are no more results. Use `while ( cursor.hasNext() ) { cursor.next() }` or `for result of cursor` loops to iterate cursors.

**Returns**

Object

### QueryCursor.passthru()

Opens a cursor (without fetching any results) which can be returned from a route script and streamed directly through the api. When returned, the script is detached and the cursor remains open until it's exhausted, incurring no further script ops or serialization costs. This is ideal for returning query results that do not require any post-query in-script processing.\
\- Without passthru: return org.objects.c\_example.find().toList() (script->api->script->api->response)\
\- With passthru: return org.objects.c\_example.find().limit(10).passthru() (script->api->response)

**Returns**

Object

### QueryCursor.pathPrefix(path = null)

Sets the query prefix for retrieving a nested List property. All cursor options are passed through the path down to the list (including grant and skipAcl). Compatible with `next()`, `toArray()`, and with `passthru()` (to retrieve a streamable cursor). For example, `org.objects.c_grandparent.find().pathPrefix( '5a2c44bc8664e438e45387d5.c_parents.5a2c44f88664e438e45387d6.c_children' ).where( {c_prop: value} )` passes the where() option down through 2 list properties to the c\_parents.c\_children.

**Arguments**

* `path` (String) Path to a list property.

**Returns**

Object

### QueryCursor.pathRead(path, options)

Returns the first matching document single path base on the current cursor options.

**Arguments**

* `path` (String) Property path to read (Reading through references and lists is supported. eg `"/creator/name/first"`).
* `options` (Object)
  * `throwNotFound` (Boolean) Defaults to true. If false, will return null if no match is found.

**Returns**

Object

### QueryCursor.paths(...props)

Limits the result properties to `...props`. Only properties specified here (and those include()/expand()) are included in the results. Expandable reference properties and optional properties can also be listed here instead, limiting the output of those properties. For example, `cursor.paths('c_parent.owner.name')` jumps through the c\_parent reference and it's owner reference to return the name property. Path lookups through references requires appropriate access permissions.

**Arguments**

* `...props` (String) Property paths to return in results.

**Returns**

this

### QueryCursor.reduce(fn, memo)

Exhausts the cursor, calling `fn` with memo for each document, and returning `memo`. Because `reduce()` iterates through the cursor, the caller should set a sane `limit()`.

**Arguments**

* `fn` (Function) a function to call for each result in the form of `(memo, document) => { return memo; }`.
* `memo` (Object) an initial value for `fn`.

**Returns**

Object

### QueryCursor.skip(count)

Skips `count` number of results. Please not that large offsets can be expensive and slow down your query. It's more efficient to use range queries.

**Arguments**

* `count` (Number) The number of results to skip.

**Returns**

this

### QueryCursor.skipAcl(bool = true)

Skips initial lookup access control checks. Use in conjunction with `grant()` to set property level access.

**Arguments**

* `bool` (Boolean)

**Returns**

this

### QueryCursor.sort(object)

Sets the sort options (e.g. `{c_num_prescriptions: -1, c_fullname: 1}`);

**Arguments**

* `sort` (Object) an object containing indexed, sortable properties to sort on and their direction (1, -1)

**Returns**

this

### QueryCursor.stream(fnEach, fnMap)

Exhausts the cursor, setting the content type to `application/json` and writing directly to the Response as a list object. Values returned from the script after stream is called are ignored.

**Arguments**

* `fnEach` (Function) optional function - `(result, total) => { return false; }` - called after each item is written. Returning `false` ends the stream early.
* `fnMap` (Function) optional function - `(result) => { return result; }` - called to transform each result before output, the result of which is JSON.stringify()'d.

**Returns**

undefined

### QueryCursor.where(filter)

Overwrites the initial filter passed in the constructor.

**Arguments**

* `filter` (Object)

**Returns**

thisJavaScript

```
const skip = require('request').params.skip;

const cursor = org.objects.c_nums
  .find()
  .paths('_id')
  .skipAcl()
  .skip(skip)
  .grant(1)
  .limit(10000)

return cursor.passthru();
```

### QueryCursor.toArray()

Exhausts the cursor and returns an array of results (not a list! see toList() ). Because `toArray()` iterates through the cursor, the caller should set a sane `limit()`.

**Returns**

Object\[]

### QueryCursor.toList()

Returns a list object based on `limit()` (or the default limit of 10).

**Returns**

List (`{object: 'list', data: [...], hasMore: true}`)

## AggregationCursor

Cursor defaults are access(1), batchSize(100), grant(null), maxTimeMs(2000), skipAcl(false).

access(level)\
batchSize(sz)\
close()\
forEach(fn)\
grant(level = null)\
group(object)\
hasNext()\
isClosed()\
limit(count)\
map(fn)\
match(object)\
maxTimeMS(ms)\
next()\
passthru()\
pathPrefix(path = null)\
project(object)\
reduce(memo, fn)\
skip(count)\
skipAcl(bool = true)\
sort(object)\
stream(fnEach, fnMap)\
toArray()\
toList()\
unwind(prop)

Exhausting a db.AggregationCursor

```
const cursor = org.objects.account
  .aggregate()
  .skipAcl()
  .grant(consts.accessLevels.read)
  .sort({
    'name.first': 1
  })
  .project({
    _id: 1,
    'name.first': 1
  })
  .limit(50);

const first_names = []; 
for (let account of cursor) {
  first_names.push( account.name.first );
}
return first_names;

// OR return cursor.map(v => v.name.first)
```

Reading accounts using db.AggregationCursor and streaming

```
const cursor = org.objects.account
  .aggregate()
  .skipAcl() 
  .grant(consts.accessLevels.read)
  .sort({
    'name.first': 1
  })
  .project({
    _id: 1,
    first_name: 'name.first'
  })
  .limit(50)
  .stream(); // stream json directly to the response object.
```

### AggregationCursor.access(level)

Sets the minimum context access level the caller needs to return results. To return only results to which the caller has update access, for example, call `cursor.access(consts.accessLevels.update)`.

**Arguments**

* `level` (Number)

**Returns**

this

### AggregationCursor.batchSize(sz)

Sets the internal cursor batch size for fetching results. Normally, the default is optimal but in cases where a large number of very small documents is being fetched, a larger batch size may be slightly more performant.

**Arguments**

* `sz` (Number) The internal cursor batch size (between 1 and 1000).

**Returns**

this

### AggregationCursor.close()

Releases the cursor resources. It's not necessary to close cursors as this is done automatically when a script ends or is exhausted, but in some cases a script may need to free up a cursor mid-stream in order to open up another one.

**Returns**

this

### AggregationCursor.forEach(fn)

Executes the cursor, calling `fn` with each document.

**Arguments**

* `fn` (Function) a function to call for each element in the form of `(document) => {}`.

**Returns**

undefined

### AggregationCursor.grant(level = null)

Sets the property grant level for the operation.

**Arguments**

* `level` (Number)

**Returns**

this

### AggregationCursor.group(object)

Adds a $group stage to the aggregation.

**Arguments**

* `object` (Object)

**Returns**

this

### AggregationCursor.hasNext()

Executes the cursor, returning true if `next()` can be safely called to fetch the next result.

**Returns**

bool

### AggregationCursor.isClosed()

Returns true if a cursor has been opened and has been subsequently closed or exhausted.

**Returns**

Boolean

### AggregationCursor.limit(count)

Adds a $limit stage to the aggregation. By default, the script `toList()` limit is 10, though cursors have no default limit.

**Arguments**

* `count` (Number)

**Returns**

this

### AggregationCursor.map(fn)

Exhausts the cursor, calling `fn` with each document, and returning an array of results. Because `map()` iterates through the cursor, the caller should set a sane `limit()`.

**Arguments**

* `fn` (Function) a function to call for each result in the form of `(document) => { return document; }`.

**Returns**

Object\[]

### AggregationCursor.match(object)

Adds a $match stage to the aggregation.

**Arguments**

* `object` (Object)

**Returns**

this

### AggregationCursor.maxTimeMs(ms)

Set the maximum time a query is allowed to run.

**Arguments**

* `ms` (Number) A number between 10 and 10000.

**Returns**

this

### AggregationCursor.next()

Returns the next result. Throws a RangeError is there are no more results. Use `while ( cursor.hasNext() ) { cursor.next() }` or `for result of cursor` loops to iterate cursors.

**Returns**

Object

### AggregationCursor.passthru()

Opens a cursor (without fetching any results) which can be returned from a route script and streamed directly through the api. When returned, the script is detached and the cursor remains open until it's exhausted, incurring no further script ops or serialization costs. This is ideal for returning query results that do not require any post-query in-script processing.\
\- Without passthru: return org.objects.c\_example.aggregate().toList() (script->api->script->api->response)\
\- With passthru: return org.objects.c\_example.aggregate().limit(10).passthru() (script->api->response)

**Returns**

Object

### AggregationCursor.pathPrefix(path = null)

Sets the pipeline prefix for retrieving a nested List property. All cursor options are passed through the path down to the list (including grant and skipAcl). Compatible with `next()`, `toArray()`, and with `passthru()` (to retrieve a streamable cursor). For example, `org.objects.c_grandparent.aggregate().pathPrefix( '5a2c44bc8664e438e45387d5.c_parents.5a2c44f88664e438e45387d6.c_children' ).match( {c_prop: value} )` passes the match() option down through 2 list properties to the c\_parents.c\_children.

**Arguments**

* `path` (String) Path to a list property.

**Returns**

Object

### AggregationCursor.project(object)

Adds a $project stage to the aggregation.

**Arguments**

* `object` (Object)

**Returns**

this

### AggregationCursor.reduce(fn, memo)

Exhausts the cursor, calling `fn` with memo for each document, and returning `memo`. Because `reduce()` iterates through the cursor, the caller should set a sane `limit()`.

**Arguments**

* `fn` (Function) a function to call for each result in the form of `(memo, document) => { return memo; }`.
* `memo` (Object) an initial value for `fn`.

**Returns**

Object

### AggregationCursor.skip(count)

Skips `count` number of results. Please not that large offsets can be expensive and slow down your query. It's more efficient to use range queries.

**Arguments**

* `count` (Number) The number of results to skip.

**Returns**

this

### AggregationCursor.skipAcl(bool = true)

Skips initial lookup access control checks. Use in conjunction with `grant()` to set property level access.

**Arguments**

* `bool` (Boolean)

**Returns**

this

### AggregationCursor.sort(object)

Adds a $sort stage to the aggregation.

**Arguments**

* `object` (Object)

**Returns**

this

### AggregationCursor.stream(fnEach, fnMap)

Exhausts the cursor, setting the content type to `application/json` and writing directly to the Response as a list object. Values returned from the script after stream is called are ignored.

**Arguments**

* `fnEach` (Function) optional function - `(result, total) => { return false; }` - called after each item is written. Returning `false` ends the stream early.
* `fnMap` (Function) optional function - `(result) => { return result; }` - called to transform each result before output, the result of which is JSON.stringify()'d.

**Returns**

undefined

### AggregationCursor.toArray()

Exhausts the cursor and returns an array of results (not a list! see toList() ). Because `toArray()` iterates through the cursor, the caller should set a sane `limit()`.

**Returns**

Object\[]

### AggregationCursor.toList()

Returns a list object based on `limit()` (or the default limit of 10).

**Returns**

List (`{object: 'list', data: [...], hasMore: true}`)

### AggregationCursor.unwind(prop)

Adds an $unwind stage to the aggregation.

**Arguments**

* `prop` (String) the property to unwind.

**Returns**

this
