Caching your mongoose Queries and Aggregate (in-memory, redis)
Published: 2023-04-29 13:40:24

When building a Node.js application that uses MongoDB as its data store, you might find that queries and aggregates can become slow as your data grows. This can be especially problematic when you have to execute the same query multiple times within a short period of time. In such cases, caching can be a powerful technique to improve performance and reduce the load on your database.

In this post, we’ll explore how to use [ts-cache-mongoose](https://www.npmjs.com/package/ts-cache-mongoose) to speed up Mongoose queries and aggregates.

In-memory cache can be a powerful tool for improving the performance of applications that require fast access to frequently accessed data.

Redis is often used as a cache because it is very fast and can store data in memory shared between multiple instances if your application, reducing the need to fetch data from a slower data source such as a database.

Why Cache Mongoose Queries and Aggregates?

When a Node.js application makes a query to a MongoDB database, the database has to search through all the documents in the collection to find the documents that match the query. This process can be slow, especially if the collection contains a large number of documents.

If the same query is executed multiple times within a short period of time, it can put a significant load on the database, reducing the performance of the application. By caching the results of the query in Redis, subsequent queries can be served from the cache instead of the database, reducing the load on the database and improving performance.

In addition, caching can also help reduce the cost of using a database service such as MongoDB, as it can reduce the number of queries that need to be executed.

How to Cache Mongoose Queries and Aggregates with [ts-cache-mongoose](https://www.npmjs.com/package/ts-cache-mongoose)?

```bash
npm install ts-cache-mongoose
yard add ts-cache-mongoose
```

This plugin requires mongoose >=6.6.x || 7.x to be installed as a peer dependency

```bash
# For mongoose 6
npm install mongoose@legacy
yarn add mongoose mongoose@legacy
# For mongoose 7
npm install mongoose@latest
yarn add mongoose@latest
```

Then just use it in your application of choice

```typescript
// On your application startup
import mongoose from 'mongoose'
import cache from 'ts-cache-mongoose'

// In-memory example 
cache.init(mongoose, {
  engine: 'memory',
})

// Redis example
cache.init(mongoose, {
  engine: 'redis',
  engineOptions: {
    host: 'localhost',
    port: 6379,
  },
})

mongoose.connect('mongodb://localhost:27017/my-database')

// Somewhere in your code
const users = await User.find({ role: 'user' }).cache('10 seconds').exec()
// Cache hit
const users = await User.find({ role: 'user' }).cache('10 seconds').exec()

const book = await Book.findById(id).cache('1 hour').exec()
const bookCount = await Book.countDocuments().cache('1 minute').exec()
const authors = await Book.distinct('author').cache('30 seconds').exec()

const books = await Book.aggregate([
  {
    $match: {
      genre: 'fantasy',
    },
  },
  {
    $group: {
      _id: '$author',
      count: { $sum: 1 },
    },
  },
  {
    $project: {
      _id: 0,
      author: '$_id',
      count: 1,
    },
  }
]).cache('1 minute').exec()
```

Typescript, Mongoose, Mongodb, Cache