It's simple, but you have to also fetch all the keys and combine them. I suggest using async to make the calls asynchronous:
function getAllUsersInChannel_suboptimal(channelName, functionCallback) {
client.keys(channelName + ":user:*", function(err, userKeys) {
if (!err) {
async.map(userKeys,
function(userKey, callback) {
client.hgetall(userKey, function(err, user) {
if (!err) {
callback(null, user);
}
else {
callback(err);
}
});
},
function(err, userList) {
if (!err) {
functionCallback(null, userList);
}
else {
functionCallback(err);
}
});
}
else {
functionCallback(err);
}
});
}
Using a pattern match can drastically reduce performance even on medium sized databases. I suggest you also index the id's of the users using a set.
Create the counter key if it does not exist and set its value to 0:
SETNX <channel_name>:user:counter 0
When you add a new user, first increment the counter key, which also fetches its value:
INCR <channel_name>:user:counter => <new_id>
This will yield the new id for the user. Now you have to save a new member in the "user:index" set like so:
SADD <channel_name>:user:index <new_id>
You can now add the new user key like so:
HMSET <channel_name>:user:<new_id> <list of values>
To fetch data for all users you would first get a the list of existing users like so:
SMEMBERS <channel_name>:user:index => <list of all user ids>
For each id you would have to fetch the hash values:
asynchronous each <list of all user ids> as <user_id>
HGETALL channel_name>:user:<user_id> => all values of key
end asynchronous each
In Node.js, considering that you've already used the techniques above to index users, you retrieve all users in a channel using something like this:
function getAllUsersInChannel_optimal(channelName, functionCallback) {
client.smembers(channelName + ":user:index", function(err, userIds) {
if (!err) {
async.map(userIds,
function(userId, callback) {
client.hgetall(channelName + ":user:" + userId, function(err, user) {
if (!err) {
callback(null, user);
}
else {
callback(err);
}
});
},
function(err, userList) {
if (!err) {
functionCallback(null, userList);
}
else {
functionCallback(err);
}
});
}
else {
functionCallback(err);
}
});
}