# Introduction to Mongoose Queries

By Atta Ur Rehman Shah (https://attacomsian.com/about). Published Jun 25, 2022, updated Jun 26, 2022. Topics: Node.js, Mongoose, MongoDB.
Canonical URL: https://attacomsian.com/blog/mongoose-queries

> An introduction to Mongoose queries and how to use the Query object to find, update and delete documents from a MongoDB collection.

Mongoose [models](https://attacomsian.com/blog/mongoose-models#querying-documents) provide several functions for querying, updating, and deleting documents from a MongoDB collection. All of these functions return a Mongoose `Query` object.

```javascript
const mongoose = require('mongoose')
const { Schema } = mongoose

const productSchema = new Schema({
  name: String,
  color: String,
  price: Number
})

const Product = mongoose.model('Product', productSchema)

const query = Product.findOne({ name: 'iPhone XL' })

// Execute query
const doc = await query
```

## Executing queries

There are two ways to execute a Mongoose query. You can either pass in a callback function or use the `then()` method to execute the query as a promise.

When executing a query with a callback function, you need to pass your query filters as a JSON object:

```javascript
Product.findOne({ name: 'iPhone XL' }, (err, doc) => {
  if (err) {
    console.log(`Error: ${err}`)
    return
  }

  console.log(doc)
})
```

Mongoose will execute the above query and pass the results to the callback function. If an error occurs executing the query, the `err` parameter will contain an error document, and the `doc` object will be `null`. If the query executes successfully, the `err` parameter will be `null`, and the `doc` will be populated with the results.

Mongoose queries are not native [JavaScript promises](https://attacomsian.com/blog/promises-javascript). But they have `then()` and `catch()` methods to execute queries as a promise.

```javascript
Product.findOne({ name: 'iPhone XL' })
  .then(doc => console.log(doc))
  .catch(err => console.log(`Error: ${err}`))
```

Finally, you can also use [async-await](https://attacomsian.com/blog/async-await-javascript) syntax to execute a Mongoose query:

```javascript
try {
  const doc = await Product.findOne({ name: 'iPhone XL' })
  console.log(doc)
} catch (err) {
  console.log(`Error: ${err}`)
}
```

## Chaining

Instead of specifying query filters as a JSON object, you can also use Mongoose's query helpers to build up query filters using chaining syntax.

Let us rewrite the above query using `Query` helper functions:

```javascript
const doc = await Product.find().where('name').equals('iPhone XL')
```

Here is another example that uses several helper functions to build a query:

```javascript
const doc = await Product.find()
  .where('name')
  .in(['iPhone XL', 'Snap X'])
  .where('price')
  .gte(5.99)
  .lte(10)
  .limit(5)
  .sort({ name: 1 })
  .select('name price')
```

A complete list of all available `Query` helper functions can be found on Mongoose's [API docs](https://mongoosejs.com/docs/api.html#query-js). 

## Streaming

You can call the Mongoose's `Query.cursor()` helper method to stream query results from a MongoDB collection. This method returns an instance of `QueryCursor`:

```javascript
const cursor = Product.find().cursor()

for (let doc = await cursor.next(); doc != null; doc = await cursor.next()) {
  console.log(doc)
}
```

Iterating through a Mongoose query also creates a cursor, as shown below:

```javascript
for await (const doc of Product.find()) {
  console.log(doc)
}
```
