Чтобы сделать это еще на один шаг, можно ли как zrangebyscore, так и получить все пользовательские объекты за один звонок?
Я не верю, что вы можете. Команда SORT имеет встроенную функциональность GET, которая позволяет вам делать такую вещь за один вызов, но нет способа передать результаты ZRANGEBYSCORE в SORT (запрет на сохранение его во временном ключе, а затем использование SORT на этом ключе).
Существует также естественный способ получить несколько хэшей в один звонок.
С вашей текущей реализации, с учетом этих ограничений, вы можете получить все пользователи с несколькими, например:
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. Краткое объяснение: сценарий принимает начальный и конечный диапазон для возраста пользователя, затем любое количество хэш-ключей, которое он использует для 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.
Если мне нужно использовать мульти, все равно, что я могу получить все данные сразу, когда я, наконец, отправлю его? (IE без необходимости иметь дело с обратным обращением) – Billy
Не обойдя то же самое в сценарии lua. В противном случае вы смотрите на 2 запроса, получая ключи из набора, а затем отправляете мульти, чтобы получить хеши. В luascript вы можете пропустить multi и просто запустить hgetalls самостоятельно, упаковать их и вернуть весь список, а затем обработать их обратно вместе аналогично тому, как я это делаю во втором примере. (Обычно node_redis автоматически сопоставляет hgetalls с объектами) – numbers1311407