# Mongoose

# Queries

A `Query` is what is returned when calling many `Model` methods. These `Query` objects provide a chaining api to specify search terms, cursor options, hints, and other behavior.

## Query#where

Lets you specify query terms with sugar.

    query.where(path [, val])

`path` is a valid document path. `val` is optional. Its useful to omit `val` when used in conjunction with other query methods. For example:

    query
    .where('name', 'Space Ghost')
    .where('age').gte(21).lte(65)
    .exec(callback)

In this case, `gte()` and `lte()` operate on the previous path if not explicitly passed. The above query results in the following query expression:

    { name: 'Space Ghost', age: { $gte: 21, $lte: 65 }}

## Query#$where

Specifies the javascript function to run on MongoDB on each document scanned. See the MongoDB docs for details.

    Model.find().$where(fn)

`fn` can be either a function or a string.

## Query#or

Specifies the $or operator.

    query.or(array);

`array` is an array of expressions.

    query.or([{ color: 'blue' }, { color: 'red' }]);

## Query#nor

Specifies the $nor operator.

    query.nor(array);

`array` is an array of expressions.

    query.nor([{ color: 'daffodil yellow' }, { color: 'atomic tangerine' }]);

## Query#equals

Assigns `val` to the last path used in `where()`.

    query.where(path).equals(val)

    // same as

    query.where(path, val);

## Query#gt

Specifies a greater than expression.

    query.gt(path, val);

`gt` is also one of the methods with extra chaining sugar: when only one argument is passed, it uses the path used the last call to `where()`. Example:

    Model.where('age').gt(21)

Results in:

    { age: { $gt: 21 }}

## Query#gte

Specifies a greater than or equal to expression.

    query.gte(path, val);

`gte` is also one of the methods with extra chaining sugar: when only one argument is passed, it uses the path used the last call to `where()`. Example:

    Model.where('age').gte(21)

Results in:

    { age: { $gte: 21 }}

## Query#lt

Specifies a less than expression.

    query.lt(path, val);

`lt` is also one of the methods with extra chaining sugar: when only one argument is passed, it uses the path used the last call to `where()`. Example:

    Model.where('age').lt(21)

Results in:

    { age: { $lt: 21 }}

## Query#lte

Specifies a less than or equal to expression.

    query.lte(path, val);

`lte` is also one of the methods with extra chaining sugar: when only one argument is passed, it uses the path used the last call to `where()`. Example:

    Model.where('age').lte(21)

Results in:

    { age: { $lte: 21 }}

## Query#ne

Specifies the $ne operator.

    query.ne(path, val);

These methods have extra sugar in that when only one argument is passed, the path in the last call to `where()` is used. Example:

    query.where('_id').ne('4ecf92f31993a52c58e07f6a')

results in

    { _id: { $ne: ObjectId('4ecf92f31993a52c58e07f6a') }}

## Query#in

Specifies the $in operator.

    query.in(path, array)

This method has extra sugar in that when only one argument is passed, the path in the last call to `where()` is used.

    query.where('tags').in(['game', 'fun', 'holiday'])

results in

    { tags: { $in: ['game', 'fun', 'holiday'] }}

## Query#nin

Specifies the $nin operator.

    query.nin(path, array)

This method has extra sugar in that when only one argument is passed, the path in the last call to `where()` is used.

    query.where('games').nin(['boring', 'lame'])

results in

    { games: { $nin: ['boring', 'lame'] }}

## Query#all

Specifies the $all operator.

    query.all(path, array)

This method has extra sugar in that when only one argument is passed, the path in the last call to `where()` is used.

    query.where('games').all(['fun', 'exhausting'])

results in

    { games: { $all: ['fun', 'exhausting'] }}

## Query#regex

Specifies the $regex operator.

    query.regex('name.first', /^a/i)

This method has extra sugar in that when only one argument is passed, the path in the last call to `where()` is used.

    query.where('name.first').regex(/^a/i)

results in

    { 'name.first': { $regex: /^a/i }}

## Query#size

Specifies the $size operator.

    query.size(path, integer)

This method has extra sugar in that when only one argument is passed, the path in the last call to `where()` is used.

    query.size('comments', 2)
    query.where('comments').size(2)

both result in

    { comments: { $size: 2 }}

## Query#mod

Specifies the $mod operator.

    var array = [10, 1]
    query.mod(path, array)

    query.mod(path, 10, 1)

    query.where(path).mod(10, 1)

all result in

    { path: { $mod: [10, 1] }}

## Query#exists

Specifies the $exists operator.

    query.exists(path, Boolean)

These methods have extra sugar in that when only one argument is passed, the path from the last call to `where()` is used.

Given the following query,

    var query = Model.find();

the following queries

    query.exists('occupation');
    query.exists('occupation', true);
    query.where('occupation').exists();

all result in

    { occupation: { $exists: true }}

Another example:

    query.exists('occupation', false)
    query.where('occupation').exists(false);

result in

    { occupation: { $exists: false }}

## Query#elemMatch

Specifies the $elemMatch operator.

    query.elemMatch(path, criteria)
    query.where(path).elemMatch(criteria)

Functions can also be passed so you can further use query sugar to declare the expression:

    query.where(path).elemMatch(function)
    query.elemMatch(path, function)

In this case a `query` is passed as the only argument into the function.

    query.where('comments').elemMatch(function (elem) {
      elem.where('author', 'bnoguchi')
      elem.where('votes').gte(5);
    });

Results in

    { comments: { $elemMatch: { author: 'bnoguchi', votes: { $gte: 5 }}}}

## Query#within

    query.within.box
    query.within.center

todo

## Query#box

todo

## Query#center

todo

## Query#centerSphere

todo

## Query#near

Specifies the $near operator.

    var array = [10, 1]
    query.near(path, array)

    query.near(path, 10, 1)

    query.where(path).$near(10, 1)

all result in

    { path: { $near: [10, 1] }}

## Query#maxDistance

Specifies the $maxDistance operator.

    query.where('checkin').near([40, -72]).maxDistance(1);

results in

    { checkin: { $near: [40, -72], $maxDistance: 1 }}

## Query#select

Specifies which subset of fields you want to return.

    query.select('title name'})
    // only _id, title, and name fields will be populated in your docs

You can also use object syntax:

    query.select({ age: 0, contact: 0 })
    // return everything but age and contact

## Query#only

deprecated

Specifies a subset of fields to return. This is like `select()` but this option only specifies which fields you want returned.

    query.only('title name')
    query.only('title', 'name')
    query.only(['title', 'name'])

## Query#exclude

deprecated

Specifies a subset of fields to return. This is like `select()` but this option only specifies which fields you DO NOT want returned.

    query.exclude('title name')
    query.exclude('title', 'name')
    query.exclude(['title', 'name'])

## Query#slice

Retrieve a sub-range of elements in an array with the $slice method.

    query.slice(path, val)

`val` can be a Number:

    query.where('tags').slice(5) // last 5 tags
    query.where('tags').slice(-5) // first 5 tags

or an Array.

    query.where('tags').slice([20, 10]) // skip 20, limit 10
    query.where('tags').slice([-20, 10]) // 20 from the end, limit 10

`slice` is also one of the methods with extra chaining sugar: when only one argument is passed, it uses the path used the last call to `where()`. Example:

    query.slice('tags', -5)

is the same as

    query.where('tags').slice(-5)

## Query#populate

Specifies the paths to be populated. See in-depth docs here.

# Sorting

## Query#sort

Sets the sort path and direction.

    query.sort('path', 1)
    query.sort('path', -1)
    query.sort('path', 1, 'another.path', -1)

## Query#asc

deprecated

Sorting sugar.

    query.asc('path' [, paths])

Each string `path` argument will be added to the sort ascending clause.

    query.asc('title', 'name');

Is the same as

    query.sort('title', 1).sort('name', 1);

## Query#desc

deprecated

Sorting sugar.

    query.desc('path' [, paths])

Each string `path` argument will be added to the sort descending clause.

    query.desc('title', 'name');

Is the same as

    query.sort('title', -1, 'name', -1);

# Options

## Query#limit

The limit method specifies the max number of documents to return.

    query.limit(20).skip(10)

## Query#skip

The skip method specifies at which document the database should begin returning results.

    query.skip(10).limit(20)

## Query#maxscan

Limits the number of documents to scan.
query.maxscan(Number)

## Query#snapshot

The snapshot method indicates the use of snapshot mode for the query.

    query.snapshot(Boolean)

## Query#batchSize

Sets the numer of documents to return per database query. For example, if we were qeurying for 10000 docs and streaming them to the client, we may want to limit the number of documents retrieved per cursor iteration to reduce memory consuption (all docs are held in memory during iteration). Setting `batchSize` to, say, 100, would mean that the cursor would be pulling only 100 documents at a time from MongoDB.

    query.batchSize(Number)

## Query#slaveOk

Sets the slaveOk option or `true` with no arguments.

    query.slaveOk(Boolean)
    query.slaveOk() // equivalent to query.slaveOk(true)

## Query#tailable

Sets the tailable option or `true` with no arguments.

    query.tailable(Boolean)
    query.tailable() // equivalent to query.tailable(true)

Tailable queries can only be used on capped collections, can only return documents in their natural order, and never use indexes. Unless the cursor dies, a tailable QueryStream will remain open and receive documents as they are inserted into the collection, much like the Unix `tail -f` command.

    var stream = Model.find().tailable().stream();

    stream.on('data', function (doc) {
        // do stuff
    });

## Query#hint

Specifies the hint option for MongoDB.

    query.hint(indexName)

If your schema has an index like

    Thing.index({ name: 1, title: 1 })

and you wanted to tell MongoDB to use that index for your query (in the off chance that MongoDB was not able to figure our that it should use it) you can give MongoDB a hint like so:

    query.hint({ name: 1, title: 1}).exec(callback)

## Query#comment

Sets the comment option.

    query.comment(String)

# Executing

## Query#find

    query.find(criteria [, callback])

## Query#findOne

Sends the findOne command to MongoDB.

    query.findOne([callback])

## Query#count

Sends the count command to MongoDB.

    query.count(callback)

## Query#distinct

Casts `field` and sends a distinct command to MongoDB.

    query.distinct(field, callback)

## Query#update

Casts the `doc` according to the model Schema and sends an update command to MongoDB.

    query.update(doc, callback)

All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility.

    query.update({..}, { title: 'remove words' }, ...)

becomes

    query.update({..}, { $set: { title: 'remove words' }}, ...)

## Query#remove

Casts the query, then sends the remove command to MongoDB.

    query.remove(callback)

## Query#exec

Executes the query passing the results to the optional `callback`.

    query.exec([callback])

Typically used in chaining scenarios:

    Model.findOne().where('points').$gt(1000).exec(function (err, doc) {
      if (err) ...
    });

## Query#each

deprecated

A streaming cursor interface.

2.4.0 introduces the query.stream() method which is a more 'node-like' way of streaming records and provides better cursor management. It is recommended that you use query.stream in place of query.each.

    query.each(callback);

The `callback` is called repeatedly for each document found as its streamed. If an error occurs streaming stops.

    query.each(function (err, user) {
      if (err) return res.end("aww, received an error. all done.");
      if (user) {
        res.write(user.name + '\n')
      } else {
        res.end("reached end of cursor. all done.");
      }
    });

A third parameter may also be used in the callback which allows you to iterate the cursor manually.

    query.each(function (err, user, next) {
      if (err) return res.end("aww, received an error. all done.");
      if (user) {
        res.write(user.name + '\n')
        doSomethingAsync(next);
      } else {
        res.end("reached end of cursor. all done.");
      }
    });

## Query#stream

Returns a QueryStream for the query.

    Model.find({}).stream().pipe(writeStream)

See the QueryStream docs for details.