'mongoose.Query.prototype.exec() patching not working with populate
This is the code I have written for implementing redis caching in queries:
mongoose.Query.prototype.exec = async function () {
if (!this.__useCache || !client.__connected) {
return exec.apply(this);
}
const key = JSON.stringify(
Object.assign({}, this.getQuery(), {
collection: this.mongooseCollection.name,
})
);
// see if key exists
const cachedValue = await client.HGET(this.__hashKey, key);
// if yes, return it
if (cachedValue) {
const doc = JSON.parse(cachedValue);
const result = Array.isArray(doc)
? doc.map((d) => new this.model(d))
: new this.model(doc);
console.log('result', result);
return result;
}
// if no, store it in redis and return
const result = await exec.apply(this);
if (typeof result === 'object') {
await client.HSET(this.__hashKey, key, JSON.stringify(result));
// cache will expire after 24 hrs by default
client.expire(this.__hashKey, this.__duration || 86400);
}
return result;
};
This works perfectly fine for all queries that doesn't 'populate'. But with populate it gets stuck at await exec.apply(this). Why does it happen and how do I fix it ?
Solution 1:[1]
I solved it by saving the reference to original exec() inside the Query object instead of just a local variable and calling that instead of the local variable. Like this :
mongoose.Query.prototype._exec = mongoose.Query.prototype.exec;
mongoose.Query.prototype.exec = async function () {
//redis functionality
.
.
.
return await mongoose.Query.prototype._exec.apply(this, arguments);
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | anandsr-dev |