我有以下查询,这些查询以启动GetById方法开始,一旦启动并从另一个文档中提取数据,它就会保存到竞赛文档中。
我希望能够在保存十分钟后缓存数据。我看了一下cacheman库,不确定它是不是适合这项工作的工具。什么是最好的方法来解决这个问题?
getById: function(opts,callback) {
var id = opts.action;
var raceData = { };
var self = this;
this.getService().findById(id,function(err,resp) {
if(err)
callback(null);
else {
raceData = resp;
self.getService().getPositions(id, function(err,positions) {
self.savePositions(positions,raceData,callback);
});
}
});
},
savePositions: function(positions,raceData,callback) {
var race = [];
_.each(positions,function(item) {
_.each(item.position,function(el) {
race.push(el);
});
});
raceData.positions = race;
this.getService().modelClass.update({'_id' : raceData._id },{ 'positions' : raceData.positions },callback(raceData));
}
答案 0 :(得分:1)
我最近编写并发布了一个名为Monc的模块。您可以在here上找到源代码。您可以找到几种有用的方法来存储,删除和检索存储在内存中的数据。
您可以使用它来使用简单嵌套来缓存Mongoose查询
test.find({}).lean().cache().exec(function(err, docs) {
//docs are fetched into the cache.
});
否则,您可能需要查看Mongoose的核心并覆盖原型,以便像原始建议一样使用cacheman。
创建一个节点模块并强制它将Mongoose扩展为:
monc.hellocache(mongoose, {});
在您的模块中,您应该扩展Mongoose.Query.prototype
exports.hellocache = module.exports.hellocache = function(mongoose, options, Aggregate) {
//require cacheman
var CachemanMemory = require('cacheman-memory');
var cache = new CachemanMemory();
var m = mongoose;
m.execAlter = function(caller, args) {
//do your stuff here
}
m.Query.prototype.exec = function(arg1, arg2) {
return m.execAlter.call(this, 'exec', arguments);
};
})
看看Monc's source code,因为它可能是一个很好的参考,可以扩展和链接Mongoose方法
答案 1 :(得分:0)
我将使用npm redis软件包进行解释,该软件包将键/值对存储在缓存服务器中。键是查询,redis仅存储字符串。
我们必须确保密钥是唯一且一致的。因此,键值应存储查询以及正在应用查询的模型的名称。
查询时,在猫鼬库中有
function Query(conditions, options, model, collection) {} //constructor function
负责查询。在此构造函数中,
Query.prototype.exec = function exec(op, callback) {}
此函数负责执行查询。因此我们必须操纵该功能并使其执行那些任务:
首先检查我们是否有与查询相关的缓存数据 如果是,请立即回复请求并返回 如果没有,我们需要响应请求并更新缓存,然后响应
const redis = require("client");
const redisUrl = "redis://127.0.0.1:6379";
const client = redis.createClient(redisUrl);
const util = require("util");
//client.get does not return promise
client.get = util.promisify(client.get);
const exec = mongoose.Query.prototype.exec;
//mongoose code is written using classical prototype inheritance for setting up objects and classes inside the library.
mongoose.Query.prototype.exec = async function() {
//crate a unique and consistent key
const key = JSON.stringify(
Object.assign({}, this.getQuery(), {
collection: this.mongooseCollection.name
})
);
//see if we have value for key in redis
const cachedValue = await redis.get(key);
//if we do return that as a mongoose model.
//the exec function expects us to return mongoose documents
if (cachedValue) {
const doc = JSON.parse(cacheValue);
return Array.isArray(doc)
? doc.map(d => new this.model(d))
: new this.model(doc);
}
const result = await exec.apply(this, arguments); //now exec function's original task.
client.set(key, JSON.stringify(result),"EX",6000);//it is saved to cache server make sure capital letters EX and time as seconds
};
如果我们将值存储为对象数组,则需要确保将每个对象都单独转换为猫鼬文档。
this.model
是Query构造函数中的一种方法,可将对象转换为猫鼬文档。
请注意,如果要存储嵌套值而不是client.get和client.set,请使用client.hset和client.hget
现在我们猴子修补了 Query.prototype.exec
因此您不需要导出此功能。只要您在代码中进行查询操作,猫鼬都会执行以上代码