Redis中的排序

1.有序集合的集合操作

集合类型提供了强大的集合操作命令,但是如果需要排序就要用到有序集合类型。Redis为了命令的精简和高性能的操作,就没有提供使用现有命令来实现的功能,再提供额外的命令。比如想直接获取集合运算结果的情况,我们可以使用MULTI,ZINTERSTORE,ZRANGE,DEL和EXEC这5个命令:

MULTI
ZINTERSTORE tempKey
ZRANGE tempKey
DEL tempKey
EXEC

2.SORT命令

SORT命令可以对列表类型、集合类型和有序集合类型键进行排序,并且能完成与关系型数据库中的连接查询类似的操作。
现在博客中标有“java”标签的文章的ID分别是“2”,“6”,“12”和“26”,由于集合类型的元素是无序的,所以无法使用SMEMBERS命令得到排序后的结果。为了能让博客标签页面下的文章也能按照发布时间顺序排列,可以借助SORT命令实现,如下:

redis>SORT tag:java:posts
1) "2"
2) "6"
3) "12"
4) "26"

除了集合类型外,SORT命令还可以对列表类型元素和有序集合类型进行排序:

redis>LPUSH mylist 4 2 5 7 9
(integer) 5
redis>SORT mylist
1) "2"
2) "4"
3) "5"
4) "7"
5) "9"

对有序集合排序时,会忽略元素的分数,只针对元素自身的值进行排序:

127.0.0.1:6379> ZADD myzset 50 2 40 32 45 8
(integer) 3
127.0.0.1:6379> SORT myzset
1) "2"
2) "8"
3) "32"

除了使用SORT命令,我们还可以使用ALPHA命令对字典的非数字类型元素进行排序:

127.0.0.1:6379> LPUSH mylistalpha a c e d b C A
(integer) 7
127.0.0.1:6379> SORT mylistalpha
(error) ERR One or more scores can't be converted into double
127.0.0.1:6379> SORT mylistalpha ALPHA
1) "A"
2) "C"
3) "a"
4) "b"
5) "c"
6) "d"
7) "e"

SORT命令还有类似于关系型数据库的倒序排列,使用DESC:

127.0.0.1:6379> SORT mylistalpha ALPHA DESC
1) "e"
2) "d"
3) "c"
4) "b"
5) "a"
6) "C"
7) "A"

Redis的排序还支持指定查询的条数,使用LIMIT start offset:

127.0.0.1:6379> SORT mylistalpha ALPHA DESC LIMIT 1 3
1) "d"
2) "c"
3) "b"
127.0.0.1:6379>

3.BY参数

BY参数的语法为BY参考键。其中参考键可以是字符串类型键或者是散列类型键的某个字段(表示为键名->字段名)。如果提供了BY参数,SORT命令将不再依据元素自身的值进行排序,而是对每个元素使用的值替换参考键中第一个"*"并获取其值,然后依据该值对元素进行排序。

SORT tag:ruby:posts BY post:*->time DESC
1) "12"
2) "26"
3) "6"
4) "2"

上例中SORT命令会读取post:2、post:6、post:12、post:26几个散列键中的time字段的值并以此决定tag:rubyLposts键中各文章ID的顺序。
除了散列类型外,参考键还可以是字符串类型,比如:

127.0.0.1:6379> LPUSH sortbylist 2 3 1
(integer) 3
127.0.0.1:6379> SET itemscore:1 50
OK
127.0.0.1:6379> SET itemscore:2 100
OK
127.0.0.1:6379> SET itemscore:3 -10
OK
127.0.0.1:6379> SORT sortbylist BY itemscore:* DESC
1) "2"
2) "1"
3) "3"
127.0.0.1:6379>

当参考键名不包含“*”时(即常量键名,与元素值无关),SORT命令将不会执行排序操作,因为Redis认为这种情况是没有意义的(因为所有要比较的值都是一样的)。例如:

127.0.0.1:6379> SORT sortbylist BY anytext
1) "1"
2) "3"
3) "2"

例子中anytext是常量键名(甚至anytext键可以不存在),此时SORT的结果与LRANGE的结果是一样的,没有执行任何排序操作。在不需要排序但需要借助SORT命令获得与元素相关的数据时,变量键名是很有用的。
如果几个元素的参考值相同,则SORT命令会再去比较元素本身的值来决定元素的顺序。像这样:

127.0.0.1:6379> LPUSH sortbylist 4
(integer) 4
127.0.0.1:6379> SET itemscore:4 100
OK
127.0.0.1:6379> SORT sortbylist BY itemscore:* DESC
1) "4"
2) "2"
3) "3"
4) "1"
127.0.0.1:6379>

上例中“4”的参考键的值和“2”的参考键的值是一样的,都是100,所以SORT命令会再比较“4”和“2”元素本身的大小来决定二者的顺序。
当某个元素的参考键不存在时,redis会默认它的参考键值为0:

127.0.0.1:6379> LPUSH sortbylist 6
(integer) 5
127.0.0.1:6379> SORT sortbylist BY itemscore:* DESC
1) "4"
2) "2"
3) "3"
4) "6"
5) "1"

上例中的元素“6”没有设置参考键值,默认它的参考键值为0,所以排在了元素“1”(参考键值为:-10)的前面。

4.GET参数

现在有这么一个需求:上面我们对标签下的文章ID进行排序后获得了ID的列表,现在我们想获取对应文章的title。你是不是想使用HGET命令再获取对应的文章ID的标题,会不会觉得很麻烦。其实这时候我们使用SORT命令的GET参数获取排序后文章的title,就可以解决这个麻烦。
GET参数并不影响排序,他的作用是使SORT命令的返回结果不再是元素本身的值,而是你GET参数中指定的键值。GET命令支持字符串类型和散列类型的键,并使用*作为占位符。下面我们就使用GET参数直接将排序后的文章的title获取出来:

127.0.0.1:6379> SORT tag:ruby:posts BY post:*->time DESC GET post:*->title

SORT命令中还可以有多个GET参数(而BY只能有一个),所以还可以这样用:

127.0.0.1:6379> SORT tag:ruby:posts BY post:*->time DESC GET post:*->title GET post:->time

如果我们想获取文章的ID该怎么办呢,我们可以使用GET #获取键本身的值:

127.0.0.1:6379> SORT tag:ruby:posts BY post:*->time DESC GET post:*->title GET post:*->title GET #

5.STORE参数

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,163评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,301评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,089评论 0 352
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,093评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,110评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,079评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,005评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,840评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,278评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,497评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,667评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,394评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,980评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,628评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,649评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,548评论 2 352

推荐阅读更多精彩内容