If you are working with NoSQL databases and use the Mongoose package as an ODM to execute the queries on the database. This article is for you.
Why caching?
Caching is essential in optimizing performance, improving scalability, and enhancing the user experience of modern applications. It can significantly reduce the load on backend resources such as databases, or APIs. By serving cached data instead of executing resource-intensive operations.
How can we apply caching with Mongoose?
mongoose
object imported from the mongoose
package has a powerful other object called Query
. We can add to its prototype
any customized method. We will take advantage of this by creating a cache
method, to be able to apply it on any query we need to cache its results.
As shown in the following code:
import mongoose from "mongoose";
mongoose.Query.prototype.cache = async function () {
// generate unique redis key
const filterObj = this._conditions;
const options = this.options;
const modelName = this.mongooseCollection.name;
const findMethod = this.op;
const redisKey = JSON.stringify({
...filterObj,
...options,
...{ model: modelName },
...{ method: findMethod },
});
// check if the result is chached before
const cached = await client.hGet(modelName, redisKey);
if (!cached) {
const result = await mongoose.Query.prototype.exec.apply(this, arguments);
client.hSet(modelName, redisKey, JSON.stringify(result));
return result;
}
// cache the results
const cachedResults = JSON.parse(cached);
return Array.isArray(cachedResults)
? cachedResults.map((doc) => this.model.hydrate(doc))
: this.model.hydrate(cachedResults);
};
app.get("/user", async (req, res) => {
const users = await User.findOne({ age: { $gt: 30 } }).cache();
return res.json({ results: users });
});
In this code, we create a cache
method that easily can be applied to any query. The logic of this method is simple :
1- generate a unique key name.
2- check if this key has a value cached before.
3- if yes, return the cached result.
4- if no, cache the query's result and return it.
Knowing that, the values are saved in a hash table, to optimize the performance.
With Query prototype
we can add paginate
method, for instance, or any other customized method to be applied to a query and write more clean code.
Top comments (0)