使用节点js从redis服务器按模式选择所有值

时间:2014-03-13 06:00:27

标签: javascript node.js redis

我有这样的多个chanel

client.HMSET('live:user:1', {
    "a": "1",
    "b": "1"
});
client.HMSET('live:user:2', {
    "a": "2",
    "b": "2"
});
client.HMSET('live:user:3', {
    "a": "3",
    "b": "3"
});

client.HMSET('otherchanel:user:4', {
    "a": "4",
    "b": "4"
});
client.HMSET('otherchanel:user:5', {
    "a": "5",
    "b": "5"
});
client.HMSET('otherchanel:user:6', {
    "a": "6",
    "b": "6"
});

如何按键模式“live:*”选择所有值?我需要它将JSON对象重新转换为我的客户端应用程序,如下所示:

[{user:1, a:1, b:1}, {user:2, a:2, b:2}, {user:3, a:3, b:3}]

3 个答案:

答案 0 :(得分:5)

要使用模式获取所有键

client.keys('live:*', function (err, keys) {
    if (err) return console.log(err);

    for(var i = 0, len = keys.length; i < len; i++) {
        console.log(keys[i]);
    }
});

答案 1 :(得分:2)

这很简单,但您还必须获取所有密钥并将它们组合在一起。我建议使用async来使调用异步:

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);
    }
});
}

即使在中型数据库上,使用模式匹配也可以大幅降低性能。我建议您使用集合索引用户的ID。

如果计数器密钥不存在,则创建它,并将其值设置为0:

SETNX <channel_name>:user:counter 0

添加新用户时,首先递增计数器键,该键也会获取其值:

INCR <channel_name>:user:counter => <new_id>

这将为用户生成新的id。现在你必须在&#34; user:index&#34;中保存一个新成员。设置如下:

SADD <channel_name>:user:index <new_id>

您现在可以像这样添加新的用户密钥:

HMSET <channel_name>:user:<new_id> <list of values>

要获取所有用户的数据,您首先会获得现有用户的列表,如下所示:

SMEMBERS <channel_name>:user:index => <list of all user ids>

对于每个id,您必须获取哈希值:

asynchronous each <list of all user ids> as <user_id>
HGETALL channel_name>:user:<user_id> => all values of key
end asynchronous each

在Node.js中,考虑到您已经使用上述技术为用户编制索引,您可以使用以下内容检索频道中的所有用户:

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);
    }
});
}

答案 2 :(得分:2)

使用client.keys()效率非常低并且会引发CPU峰值,建议不要在生产环境中使用它。如果Redis中存储了大量数据,您应该考虑client.scan()方法,该方法将批量获取密钥。如果密钥的数量很多,它也会减少内存使用。