25

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

asked Mar 21, 2017 at 12:19
6
  • Cmon, @Bhushan -- with 3K points you'd know better than to make a question without any code... Commented Mar 21, 2017 at 12:23
  • Possible duplicate of Redis command to get all available keys? Commented Mar 21, 2017 at 12:24
  • @MoshMage I added the code. sorry as I was kinda busy Commented Mar 22, 2017 at 6:31
  • stackoverflow.com/a/38247686/3784008 Commented Mar 24, 2017 at 19:41
  • @BhushanGadekar You can check my answer below. Commented Mar 28, 2017 at 1:44

4 Answers 4

28
+100

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();
 }
 });
answered Mar 28, 2017 at 1:43
Sign up to request clarification or add additional context in comments.

1 Comment

this sounds good but not working my case as the key is of hash type client.get takes only string type
9

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.

answered Oct 4, 2017 at 14:53

4 Comments

this is not working. there is no keys property
what i really wanted to know is how to limit keys
if you want to limit then use scan method to get keys, its fast and reliable and non blocking..
5

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.

answered Mar 21, 2017 at 12:28

4 Comments

Worth to mention that the documentation explicitly states that this command should not be used to do that
@baao Yeah. I would argue that getting all keys and all values is a need that demonstrates that Redis is used in a strange way here. Unfortunately the question is about a solution, not a bout a problem, so it's hard to recommend anything else.
that Redis is used in a strange way here That's true. :D
Despite the question, a better solution would be to use SCAN instead of KEYS.
3

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?

answered Mar 29, 2017 at 7:56

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.