我遵循一个教程,创建了一个cache.js文件,该文件接受mongoose查询,json.stringifies将其放入该查询返回的值的键中。目标是缓存它,然后附加 .cache()
在app.js中 mongoose.find()
是
如果缓存是空的,我让它从数据库中获取数据,然后将其存储在缓存中。我有一个
console.log("CACHE VALUE #2");
console.log(cacheValue1);
这样可以确保数据得到存储并成功输出数据。这条线行得通。但有了这条线,
console.log("CACHE VALUE #1");
console.log(cacheValue);
这个 cacheValue
为空。
为什么?
它存储在底部的值和键从来没有改变,所以我不明白为什么它不会返回数据而不是null。
所以呢 Cache Value #1
始终为空且 Cache Value #2
有正确的数据。
控制台输出:
GRABBING FROM DB
CLIENT CONNECTION STATUS: true
Setting CACHE to True
ABOUT TO RUN A QUERY
{"$and":[{"auctionType":{"$eq":"publicAuction"}},{"auctionEndDateTime":{"$gte":1582903244869}},{"blacklistGroup":{"$ne":"5e52cca7180a7605ac94648f"}},{"startTime":{"$lte":1582903244869}}],"collection":"listings"}
CACHE VALUE #1
null
CACHE VALUE #2
(THIS IS WHERE ALL MY DATA SHOWS UP)
const mongoose = require('mongoose');
const redis = require('redis');
const util = require('util');
var env = require("dotenv").config({ path: './.env' });
const client = redis.createClient(6380, process.env.REDISCACHEHOSTNAME + '.redis.cache.windows.net', {
auth_pass: process.env.REDISCACHEKEY,
tls: { servername: process.env.REDISCACHEHOSTNAME + '.redis.cache.windows.net' }
});
client.get = util.promisify(client.get);
const exec = mongoose.Query.prototype.exec;
mongoose.Query.prototype.cache = function () {
this.useCache = true;
console.log("Setting CACHE to True")
return this;
}
mongoose.Query
.prototype.exec = async function () {
if (!this.useCache) {
console.log("GRABBING FROM DB")
console.log("CLIENT CONNECTION STATUS: " + client.connected);
return exec.apply(this, arguments);
}
console.log("ABOUT TO RUN A QUERY")
const key = JSON.stringify(Object.assign({}, this.getQuery(), {
collection: this.mongooseCollection.name
}));
//See if we have a value for 'key' in redis
console.log(key);
const cacheValue = await client.get(key);
console.log("CACHE VALUE #1");
console.log(cacheValue);
//If we do, return that
if (cacheValue) {
console.log("cacheValue IS TRUE");
const doc = JSON.parse(cacheValue);
return Array.isArray(doc)
? doc.map(d => new this.model(d))
: new this.model(doc);
}
//Otherwise, issue the query and store the result in redis
const result = await exec.apply(this, arguments);
let redisData = JSON.stringify(result);
//stores the mongoose query result in redis
await client.set(key, JSON.stringify(redisData)), function (err) {
console.error(err);
}
const cacheValue1 = await client.get(key);
console.log("CACHE VALUE #2");
console.log(cacheValue1);
return result;
}
2条答案
按热度按时间9rbhqvlz1#
我在一个很小的例子中复制了你的代码,我让它按照你的要求工作。它在第一个请求之后服务于redis缓存的响应。我刚刚记录了一些值并在代码中发现了一些小错误,您将很容易发现它们(用doc调用this.model,修复集合并删除redis客户端的最后一个get)。我不认为这是缓存响应的最佳方式,因为您在每个请求中都将一个变量设置为true,并且在使用缓存之前访问mongo和mongoose。通过中间件,所有这些都可以避免,您将带走更多ms,但这仍然不是最坏的方式,因此这里是我的最小工作示例。
ssgvzors2#
根据您链接的粘贴箱,您的查询将使用
Date.now()
他们的价值观。这意味着每次运行查询时,时间戳的值都不同。因为您的键是实际的查询,并且查询具有基于
Date.now()
,您的键将永远不会相同,这就是为什么以后在缓存中找不到它们的原因,每个查询都会生成一个唯一的键,因为Date.now()
.