node.js - Node Redis : How to filter a sorted set of keys and retrieve each keys hashed values in one call

标签 node.js nosql redis node-redis

我正在使用 node_redis 在 node.js 中使用 redis 数据库.这是一个类似于我正在使用的结构的简单示例。

hmset('user:1234', 
    'user_id', 1234, 
    'user_name', billy, 
    'user_age', 16);
//add user to group 1 store their id with their age as their score
zadd(['group:1:users_by_age', 16, user:1234]);

hmset('user:1235', 
    'user_id', 1235, 
    'user_name', jake, 
    'user_age', 21);
//add user to group 1 store their id with their age as their score
zadd(['group:1:users_by_age', 21, user:1235]);

现在假设我想获取 group:1 中 18 岁以上用户的所有用户数据

我知道我可以通过调用获取用户 key

postClient.zrangebyscore( 
    [ 'group:1:users_by_age', '18', '+inf'],
    function( err, results ){
        console.log(results);
    }
);

我迷路的地方是如何一次获取所有用户对象? 更进一步,是否可以在一次调用中同时获取 zrangebyscore 和获取所有用户对象?

最佳答案

To take it one step further, is it possible to both zrangebyscore and get all the userobjects in one call?

我不相信你可以。 SORT 命令具有内置的 GET 功能,允许您在一次调用中执行此类操作,但无法将 ZRANGEBYSCORE 的结果通过管道传输到 SORT(除非将其存储在临时键中,然后在该键上使用 SORT)。

也没有自然的方法可以在一次调用中检索多个哈希值。

在您当前的实现中,考虑到这些限制,您可能会为所有用户提供一个 multi,例如:

postClient.zrangebyscore([...], function (err, results) {
  var multi = postClient.multi();
  for (var i=0; i<results.length; i++){
    multi.hgetall(results[i]);
  }
  multi.exec(function(err, users){
    console.log(users);
  });
});

不过,您可以使用 luascript 执行此操作,检索键列表并对其进行迭代,对每个键调用 hmget 或 hgetall。

我在下面的例子中做了类似的事情,使用 hmget 和特定的键。

明确免责声明:我不是 lua 程序员。简要说明:该脚本采用用户年龄的开始和结束范围,然后是它在每个用户 key 上用于 hmget 的任意数量的哈希键,并将其全部附加到一个数组中,该数组将作为用户对象包装回 javascript .

var script = '\
local keys = redis.call("ZRANGEBYSCORE", KEYS[1], ARGV[1], ARGV[2]); \
if not keys then return {} end; \
local users, attrs = {}, {} \
for i=3,#ARGV do \
  table.insert(attrs, ARGV[i]) \
end \
for i,key in pairs(keys) do \
  local vals = redis.call("HMGET", key, unpack(attrs)); \
  if vals then \
    for j,val in pairs(vals) do \
      table.insert(users, val) \
    end \
  end \
end \
return users \
';

// The rest of this you'd probably want to wrap up in an async function, 
// e.g `getUsersByRange`

// specify the user attributes you want
var attrs = ["id", "name", "age"];

// specify the range
var range = [18, "+INF"];

// get the attributes length, used to build the user objects
var attrlen = attrs.length;

// wrap up the params
var params = [script, 1, "users_by_age"].concat(range).concat(attrs);

// retrieve the user attributes in the form of [a1, a2, a3, a1, a2, a3, ... ],
// then collate them into an array of user objects like hgetall would return.
postClient.eval(params, function (err, res) {
  var users = [], i, j, k;
  for (i=0, j=0; i<res.length; i+=attrlen, j++) {
    users[j] = {};
    for (k=0; k<attrlen; k++) {
      users[j][attrs[k]] = res[i+k];
    }

    // this should be a list of users
    console.log(users);
  }
});

请注意,在 lua 脚本中将用户处理回对象是微不足道的,但是当转换回 redis 数据结构时,lua 表变为 redis 多批量回复(数组),并且结构将丢失。因此,有必要将多批量回复转换回 javascript 中的用户对象。

关于node.js - Node Redis : How to filter a sorted set of keys and retrieve each keys hashed values in one call,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16323438/

相关文章:

ios - 使用 Node (fs writeStreams)保存图像将标题插入文件

node.js - 使用 session.socket.io-express 4 未定义 session

node.js - 在键值存储中保存带有修订的文档的最佳方法是什么?

java - com.mongodb.DB.authenticate(String,String) 是在内存中进行身份验证还是调用 mongo db?

amazon-web-services - 用于 Redis 引擎 CPU 利用率指标的 AWS ElastiCache,如何解释?

javascript - Action Cable 仅向客户端发送欢迎和 ping 消息

node.js - 如何在 Kubernetes Pod 内调试 NodeJS 应用程序?

node.js - 唯一标识HTTPS证书

mysql - Redshift 使用 - 每个用户 1 行 x 400 列或每个用户(20-400)行 x 4 列

java - Spring Redisson哨兵错误-至少需要两个哨兵