美文网首页
Redis中的排序

Redis中的排序

作者: 郭之源 | 来源:发表于2016-08-25 10:20 被阅读276次

    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参数

    相关文章

      网友评论

          本文标题:Redis中的排序

          本文链接:https://www.haomeiwen.com/subject/suymsttx.html