【发布时间】:2020-06-08 09:03:28
【问题描述】:
我正在学习一个教程,并创建了一个 cache.js 文件,该文件采用 mongoose 查询并将其 JSON.stringify 为该查询返回的值的键。目标是缓存它,然后在 app.js 中附加 .cache() mongoose.find()
当前,如果缓存为空,我让它从数据库中执行 GET,然后将其存储在缓存中。我有一个
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;
}
【问题讨论】:
-
您是否使用某种 Web 框架(express、koa、restify)来提供结果,如果是的话,使用某种中间件会更容易实现
-
我正在使用带有平均堆栈的 Azure Redis,所以也可以表达。我觉得我真的很接近让它工作了。代码用
.cache()调用,像这样pastebin.com/xW1Lzr82 -
您确定查询在后续运行之间完全没有变化吗?这段代码看起来很好,除了你的密钥非常复杂(你可以散列对象并使用散列作为密钥而不是顺便说一句)。您的密钥似乎包含几个不同的时间戳,您确定这些在查询之间不会改变吗?我会记录请求之间的查询并确保它们没有改变。
标签: node.js asynchronous mongoose redis node-promisify