当前位置:嗨网首页>书籍在线阅读

14-BY参数

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

4.3.3  BY 参数

参考键虽然支持散列类型,但是“ * ”只能在“ -> ”符号前面(即键名部分)才有用,在“ -> ”后(即字段名部分)会被当成字段名本身而不会作为占位符被元素的值替换,即常量键名。但是实际运行时会发现一个有趣的结果: 上面提到了当参考键名是常量键名时 SORT 命令将不会执行排序操作,然而上例中却进行了排序,而且只是对元素本身进行排序。这是因为Redis判断参考键名是不是常量键名的方式是判断参考键名中是否包含“ * ”,而 somekey->somefield:* 中包含“ * ”所以不是常量键名。所以在排序的时候Redis对每个元素都会读取键 somekey 中的 somefield:* 字段(“ * ”不会被替换),无论能否获得其值,每个元素的参考键值是相同的,所以Redis会按照元素本身的大小排列。

很多情况下列表(或集合、有序集合)中存储的元素值代表的是对象的ID(如标签集合中存储的是文章对象的ID),单纯对这些ID自身排序有时意义并不大。更多的时候我们希望根据ID对应的对象的某个属性进行排序。回想3.6节,我们通过使用有序集合键来存储文章ID列表,使得小白的博客能够支持修改文章时间,所以文章ID的顺序和文章的发布时间的顺序并不完全一致,因此4.3.2节介绍的对文章ID本身排序就变得没有意义了。小白的博客是使用散列类型键存储文章对象的,其中 time 字段存储的就是文章的发布时间。现在我们知道ID为“ 2 ”、“ 6 ”、“ 1 2 ”和“ 26 ”的四篇文章的 time 字段的值分别为“ 1352619200 ”、“ 1352619600 ”、“ 1352620100 ”和“ 1352620000 ”(Unix时间)。如果要按照文章的发布时间递减排列结果应为“ 12 ”、“ 26 ”、“ 6 ”和“ 2 ”。为了获得这样的结果,需要使用 SORT 命令的另一个强大的参数: BY

redis> SORT sortbylist BY somekey->somefield:*   1) "1"
  2) "2"
  3) "3"
  4) "4"
  5) "5"

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

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

在上例中 SORT 命令会读取 post:2post:6post:12post:26 几个散列键中的 time 字段的值并以此决定 tag:ruby:posts 键中各个文章ID的顺序。

除了散列类型之外,参考键还可以是字符串类型,比如:

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

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

redis> SORT sortbylist BY anytext 1) "3"
2) "1"
3) "2"

例子中 anytext 是常量键名(甚至 anytext 键可以不存在),此时 SORT 的结果与 LRANGE 的结果相同,没有执行排序操作。在不需要排序但需要借助 SORT 命令获得与元素相关联的数据时(见4.3.4节),常量键名是很有用的。

如果几个元素的参考键值相同,则 SORT 命令会再比较元素本身的值来决定元素的顺序。像这样:

redis> LPUSH sortbylist 4 (integer) 4
redis> SET itemscore:4 50 OK
redis> SORT sortbylist BY itemscore:* DESC 1) "2"
2) "4"
3) "1"
4) "3"

示例中元素 " 4 " 的参考键 itemscore:4 的值和元素 "1" 的参考键 itemscore:1 的值都是50,所以 SORT 命令会再比较 " 4 ""1" 元素本身的大小来决定二者的顺序。

当某个元素的参考键不存在时,会默认参考键的值为0:

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

上例中 " 5 " 排在了 " 3 " 的前面,是因为 " 5 " 的参考键不存在,所以默认为0,而 " 3 " 的参考键值为−10。

补充知识