Created
October 8, 2022 22:31
-
-
Save zisan34/64f502944920550db2347fde9d21ed44 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* This file is responsible for caching mongo model instance for specific time. | |
* Usage example: | |
* Store.findOne(query, fields).cacheResults(1 * 60).exec(); // it'll cache result for specified seconds | |
* Store.findOne(query, fields).removeCache().exec(); // it'll remove any existing cache | |
*/ | |
// @ts-nocheck | |
import mongoose from 'mongoose'; | |
import redisClient from './redisClient'; | |
mongoose.Query.prototype.cacheResults = function (time: number) { | |
this.cache_results = true; | |
this.cacheTimeSeconds = time; | |
return this; | |
}; | |
mongoose.Query.prototype.removeCached = function () { | |
this.remove_cached = true; | |
return this; | |
}; | |
mongoose.Query.prototype.getCacheKey = function () { | |
const key = JSON.stringify({ | |
collectionName: this.mongooseCollection.name, | |
op: this.op, | |
options: this.getOptions(), | |
filter: this.getFilter(), | |
projection: this.projection(), | |
populatedPaths: this.getPopulatedPaths(), | |
}); | |
return key; | |
}; | |
const exec = mongoose.Query.prototype.exec; | |
mongoose.Query.prototype.exec = async function () { | |
if (this.remove_cached) { | |
// remove_cached is true so remove cache for the key | |
const key = this.getCacheKey(); | |
redisClient.del(key); | |
} | |
if (this.cache_results) { | |
// cache_results is true so cache result for the key | |
const key = this.getCacheKey(); | |
const cachedResults = await redisClient.get(key); | |
if (cachedResults) { | |
// if you found cached results return it; | |
const result = JSON.parse(cachedResults); | |
const options = this.getOptions(); | |
const projection = this.projection(); | |
// create model instance again from the results so that you get all the model functionalities with cached data | |
return Array.isArray(result) | |
? // eslint-disable-next-line new-cap | |
result.map((document) => new this.model(document, projection, options)) | |
: // eslint-disable-next-line new-cap | |
new this.model(result, projection, options); | |
} else { | |
// get results from Database then cache it | |
const result = await exec.apply(this, arguments); | |
redisClient.set(key, JSON.stringify(result), 'EX', this.cacheTimeSeconds); | |
return result; | |
} | |
} else { | |
return exec.apply(this, arguments); | |
} | |
}; |
I am trying to implement exactly the same logic in my app but
const result = await exec.apply(this, arguments);
this part of the code is giving me null in case of findOne
and find
calls even when matching documents are present in the DB
any idea how to overcome this problem?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks but, not working with populate ?