Reputation: 13805
I am creating a node API using javascript. I have used redis as my key value store. I created a redis-client in my app and am able to get values for perticular key.
I want to retrieve all keys along with their values. So Far I have done this :
app.get('/jobs', function (req, res) {
var jobs = [];
client.keys('*', function (err, keys) {
if (err) return console.log(err);
if(keys){
for(var i=0;i<keys.length;i++){
client.get(keys[i], function (error, value) {
if (err) return console.log(err);
var job = {};
job['jobId']=keys[i];
job['data']=value;
jobs.push(job);
});
}
console.log(jobs);
res.json({data:jobs});
}
});
});
but I always get blank array in response.
is there any way to do this in javascript?
Thanks
Upvotes: 25
Views: 69480
Reputation: 965
You should never do this. First off, it is not recommended to use KEYS *
in production. Second, this does not scale (cluster).
You can organise your cached entries into SETs and query for the items within the SET, then retrieve the references keys. This also makes invalidation easier.
Have a look at some data storage best practices.
https://redis.io/topics/data-types-intro how to get all keys and values in redis in javascript?
Upvotes: 3
Reputation: 2717
Combination of 2 requests:
import * as ioredis from 'ioredis';
const redis = new ioredis({
port: redisPort,
host: redisServer,
password: '',
db: 0
});
const keys = await redis.collection.keys('*');
const values = await redis.collection.mget(keys);
Order will be the same for both arrays.
Upvotes: 9
Reputation: 12022
First of all, the issue in your question is that, inside the for
loop, client.get
is invoked with an asynchronous callback where the synchronous for
loop will not wait for the asynchronous callback and hence the next line res.json({data:jobs});
is getting called immediately after the for
loop before the asynchronous callbacks. At the time of the line res.json({data:jobs});
is getting invoked, the array jobs
is still empty []
and getting returned with the response.
To mitigate this, you should use any promise modules like async
, bluebird
, ES6 Promise
etc.
Modified code using async module,
app.get('/jobs', function (req, res) {
var jobs = [];
client.keys('*', function (err, keys) {
if (err) return console.log(err);
if(keys){
async.map(keys, function(key, cb) {
client.get(key, function (error, value) {
if (error) return cb(error);
var job = {};
job['jobId']=key;
job['data']=value;
cb(null, job);
});
}, function (error, results) {
if (error) return console.log(error);
console.log(results);
res.json({data:results});
});
}
});
});
But from the
Redis
documentation, it is observed that usage of Keys are intended for debugging and special operations, such as changing your keyspace layout and not advisable to production environments.
Hence, I would suggest using another module called redisscan as below which uses SCAN
instead of KEYS
as suggested in the Redis
documentation.
Something like,
var redisScan = require('redisscan');
var redis = require('redis').createClient();
redisScan({
redis: redis,
each_callback: function (type, key, subkey, value, cb) {
console.log(type, key, subkey, value);
cb();
},
done_callback: function (err) {
console.log("-=-=-=-=-=--=-=-=-");
redis.quit();
}
});
Upvotes: 28
Reputation: 111506
This will get all keys but with no values:
const redis = require('redis');
const client = redis.createClient();
client.keys('*', (err, keys) => {
// ...
});
Now you need to get the values for those keys in a usual way. For example:
Promise.all(keys.map(key => client.getAsync(key))).then(values => {
// ...
});
or with async
module or in any way you like.
Upvotes: 5