Redis按字符串值排序

时间:2012-07-14 18:47:43

标签: language-agnostic redis sorted

假设你有一个散列'users',其条目将数字ID映射到JSON编码的数组,因此,例如,整数1映射到字符串{name:'John',surname:'Doe',占用:'管道工'}。

散列中项目的数字ID存储在各种列表中。因此,如果'foobar'是这些列表中的一个,要从中检索实际数据,我将运行一个简单的Lua脚本(实现服务器端连接操作)。或者,正如我刚刚学到的,我可以使用像

这样的东西
SORT foobar BY inexistent_key GET user:*

但这意味着将每个用户的数据存储到一个看起来很昂贵的单独密钥中(在我的情况下,我有很多小型集合,所以我想利用Redis压缩哈希值)。

最后一个问题是:我需要按照每个用户的姓氏,然后按姓名按字母顺序排列这些列表。在不改变基础数据模型的情况下(如果可能的话),实现这一目标的最佳方法是什么?

到目前为止,我能想到的最好的方法是将SORT命令与BY和STORE子句一起使用,即运行

SORT foobar BY surname:* STORE foobar

无论何时更改列表,但这样我需要很多密钥。如果我可以在BY子句中使用哈希,这将是理想的解决方案,在我看来。

如果我想要排序的字段有些限制(例如,只有几百个姓氏),我可以想到将字符串映射到整数并使用Redis排序集,但似乎并非如此。

2 个答案:

答案 0 :(得分:3)

您可以按哈希键排序,而不需要Lua脚本的复杂性,但您必须将Json结构中的键复制到Redis的哈希键。

以下示例具有以下结构:

用户是查询中包含用户ID的集合。

user:X 是Redis哈希,其中包含重复的名称 / 姓氏数据。

userdata:X 是您的原始用户Json哈希。


redis> hmset user:1 name First surname User
OK
redis> set userdata:1 "{occupation: 'Tester'}"
OK
redis> hmset user:2 name Last surname Violet
OK
redis> set userdata:2 "{occupation: 'Bookseller'}"
OK
redis> hmset user:3 name Middle surname Veredict
OK
redis> set userdata:3 "{occupation: 'Judge'}"
OK
redis> hmset user:4 name Ultimate surname Veredict
OK
redis> set userdata:4 "{occupation: 'Ultimate Judge'}"
OK
redis> sadd users 1
(integer) 1
redis> sadd users 2
(integer) 1
redis> sadd users 3
(integer) 1
redis> sadd users 4
(integer) 1
redis> sort users by user:*->surname get user:*->name get user:*->surname get userdata:* alpha
1) "First"
2) "User"
3) "{occupation: 'Tester'}"
4) "Middle"
5) "Veredict"
6) "{occupation: 'Judge'}"
7) "Ultimate"
8) "Veredict"
9) "{occupation: 'Ultimate Judge'}"
10) "Last"
11) "Violet"
12) "{occupation: 'Bookseller'}"

修改

我忽略了多个By只考虑最后一个条款。所以你不能在一个命令中按多个键排序。

此外,用于词典排序的SORT命令现在需要alpha修饰符。

答案 1 :(得分:1)

最后在我看来,解决我的问题的一种方法是使用Lua中提供的table.sort()函数。除了小的哈希'用户'和ID'foobar'的小列表之外,我还引入了另一个小哈希,比如'users:sort-strings',其中我存储了我想要对ID进行排序的字符串' foob​​ar'(在虚构的例子中,姓氏和名字的组合)。为了对'foobar'进行排序,我将在Redis中运行以下Lua片段,传递键为'foobar','users:sort-strings'和'foobar:tmp'(临时键)。

local lst = redis.call('LRANGE', KEYS[1], 0, -1)
local sort_function = function (id0, id1)
   local s0 = redis.call('HGET', KEYS[2], id0)
   local s1 = redis.call('HGET', KEYS[2], id1)
   return (s0 < s1)
end
table.sort(lst, sort_function)
for key, value in ipairs(lst) do
   redis.call('RPUSH', KEYS[3], value)
end
redis.call('DEL', KEYS[1])
redis.call('RENAME', KEYS[3], KEYS[1])