文档结构  
翻译进度:已翻译     翻译赏金:0 元 (?)    ¥ 我要打赏

在这篇文章中,我们会讨论一下Redis的SORT命令。

Redis提供了SORT命令,可以在保存/获取LIST、SET或者ZSET值的时候使用。

SORT命令最简单的使用方式是用在一个KEY上,如下例所示:

SORT numbers_list

这会将这个键中的值进行排序并返回。默认情况下,该命令会将键中的值按照数字大小进行排序。因此,假设我们有一组值,如下所示:

1, 110, 5

该命令会返回:

1 5 110

我们可以使用ALPHA修饰符,指定SORT命令按照字母顺序来进行排序。SORT命令支持很多的修饰符,我们将在后面的例子中加以介绍。示例代码将使用Jedis API。

第 1 段(可获 1.55 积分)

在我们的例子中,假设有一个管理个人想法的系统。如下所示:我们有一个包含系统中所有用户名的列表:

all:users [junior, francisco, ribeiro, user4]

对于每个用户,都有一个包含了该用户信息的哈希结构:

user:

user:junior
  - name: "Junior User"
  - num_ideas : "5"
  - email:"fjunior@email.com"

user:francisco
 - name: "Francisco User"
 - num_ideas: "4"
 - email: "francisco@email.com"

...

下面这个类,使用了Redis来保存示例中的所有用户及相关信息:

package br.com.xicojunior.redistest;

import java.util.HashMap;
import java.util.Map;

import redis.clients.jedis.Jedis;

public class App 
{

    public static Jedis jedis = new Jedis("localhost");   
    public static void main( String[] args ){

        String names[] = new String[]{"junior", "francisco", "ribeiro", "user4"};
        for(String name: names){
            jedis.lpush("all:users", name);
        }
        addUserHash(names[0], "Junior User", "junior@junior.com", "5");
        addUserHash(names[1], "Francisco User", "francisco@francisco.com", "4");
        addUserHash(names[2], "Ribeiro User", "ribeiro@ribeiro.com", "3");
        addUserHash(names[3], "User 4", "user@user.com", "2");

        for(String name: names){
            System.out.println(jedis.hgetAll("user:".concat(name)));
        }

        System.out.println(jedis.lrange("all:users", 0, -1));



    }

    public static void addUserHash(String username, String name, String email, String numberOfIdeas){
        Map<String, String> userProp = new HashMap<String, String>();
        userProp.put("name",name);
        userProp.put("email", email);
        userProp.put("num_ideas", String.valueOf(numberOfIdeas));

        jedis.hmset("user:".concat(username), userProp);
    }
}
第 2 段(可获 0.63 积分)

我们先来看一下下面这段示例代码:

package br.com.xicojunior.redistest;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.SortingParams;

public class SortTest {

    public static void main(String[] args) {
        Jedis jedis = new Jedis("localhost");

        //[1]对用户名进行排序
        System.out.println(jedis.sort("all:users"));
        //[ribeiro, francisco, junior, user4]

        //[2]对用户名按照字母顺序排序
        //jedis的sort方法接受一个表示修饰符的SortingParams实例
        System.out.println(jedis.sort("all:users", new SortingParams().alpha()));
        //[francisco, junior, ribeiro, user4]

    }

}

在上面的示例中,我们对键“all:users”进行了排序。在第一次尝试中,排序的结果似乎不正确,因为默认是按照数字顺序进行排序。在第二次尝试中,我们使用了ALPHA修饰符,并且使用了sort方法的一个重载版本,能够接收一个SortingParams类的实例作为参数。在这次尝试中,我们看到用户名能够按照正确的顺序进行排序。

第 3 段(可获 0.98 积分)

SORT命令有一个很棒的特性就是我们可以使用外部的值对列表排序--其它键的值.在下面的例子中,我们将根据用户拥有的想法数量对键all:users排序.也可以使用"BY"修饰符来接收键的模式.让我们一起来看看这个例子:

package br.com.xicojunior.redistest;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.SortingParams;

public class SortTest {

    public static void main(String[] args) {
        Jedis jedis = new Jedis("localhost");

        //[1] Sorting the usernames by the number of ideas
        System.out.println(jedis.sort("all:users", new SortingParams().by("user:*->num_ideas")));
        //[user4, ribeiro, francisco, junior]

        //[1] Sorting the usernames by the number of ideas DESC
        System.out.println(jedis.sort("all:users", new SortingParams().by("user:*->num_ideas").desc()));
    }

}
第 4 段(可获 0.8 积分)

在第二个示例中,我们使用外部值对usernames做了排序,在这里这个列叫"_numideas". 由于我们使用哈希列做排序,我们使用了如下模式:"_user:->numideas" .根据这个模式,我们将要查找关键字"_user:",这里的 "*" 将会被列表中的值替代.由于使用了哈希,所以需要把它绑定到列.我们使用这种方式"->fieldname_"来完成它。如果我们使用字符串键做排序,可以使用这种模式"_numideas*_", 因为每个用户的ideas中有一个键保存了数量。

第 5 段(可获 1.4 积分)

第一个例子中, 它获取值,并以升序排列. 我们也可以设置DESC,它将会按降序排序.在Jedis内部, BY和DESC是SortingParams的方法.所有的方法都会返回当前实例,我们可以使用流式风格,它将更方便我们阅读代码.

通过_SORT命令,我们也可以通过外部键或列的哈希来获取值.我们可能通过GET修饰符来完成,并且可以多次操作.让我们来看看这个修改答的示例:

package br.com.xicojunior.redistest;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.SortingParams;

public class SortTest {

    public static void main(String[] args) {
        Jedis jedis = new Jedis("localhost");

        //[1] Sorting the usernames by the number of ideas and retrieving the user name
        System.out.println(jedis.sort("all:users", new SortingParams().by("user:*->num_ideas").get("user:*->name")));
        //[User 4, Ribeiro User, Francisco User, Junior User]

        //[2] Retrieving the name and email
        System.out.println(jedis.sort("all:users", new SortingParams().by("user:*->num_ideas").get("user:*->name","user:*->email")));
        //[User 4, user@user.com, Ribeiro User, ribeiro@ribeiro.com, Francisco User, francisco@francisco.com, Junior User, junior@junior.com]


        //[3] Retrieve the value of the key being sorted - Special pattern #
        System.out.println(jedis.sort("all:users", new SortingParams().by("user:*->num_ideas").get("user:*->name","user:*->email","#")));
        //[User 4, user@user.com, user4, Ribeiro User, ribeiro@ribeiro.com, ribeiro, Francisco User, francisco@francisco.com, francisco, Junior User, junior@junior.com, junior]
    }

}
第 6 段(可获 1.28 积分)

在上面的示例中我们可以看到GET修饰符是怎么使用的.为了返回一个哈希列,我们使用了与BY修饰符类似的模式.首先,我们只是简单的返回了姓名,但正如我们所说,我们可以使用多次GET。第二点,我们在用户中检索姓名和邮箱.我们也可以检索使用特殊模式"#"排序的键的值.GET方法接收的内容长度可变,所以我们可以将需要检索值对应的所有键传递给它.

另外一件我们可以做的事就是将结果根据键排序后保存.当我们需要缓存排序结果时,它对我们来说很有用,我们可以为SORT命令指定需要排序的键.结果将被保存为LIST.

package br.com.xicojunior.redistest;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.SortingParams;

public class SortTest {

    public static void main(String[] args) {
        Jedis jedis = new Jedis("localhost");

        jedis.sort("all:users","dest_key1");

        System.out.println(jedis.lrange("dest_key1", 0, -1));
        //[ribeiro, francisco, junior, user4]

        jedis.sort("all:users", new SortingParams().alpha().desc(), "dest_key2");

        System.out.println(jedis.lrange("dest_key2", 0, -1));
        //[user4, ribeiro, junior, francisco]
    }

}
第 7 段(可获 1.89 积分)

SORT命令非常有用的功能就是:我们可以通过关联键来获取它的值.可以使用NOSORT指示符,表示不需要排序:

package br.com.xicojunior.redistest;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.SortingParams;

public class SortTest {

    public static void main(String[] args) {
        Jedis jedis = new Jedis("localhost");

        System.out.println(jedis.sort("all:users", new SortingParams().get("user:*->name","user:*->email").nosort()));
        //[User 4, user@user.com, Ribeiro User, ribeiro@ribeiro.com, Francisco User, francisco@francisco.com, Junior User, junior@junior.com]

    }

}

这段代码获取了所有用户的姓名与邮箱地址.在这里我们没有使用SORT命令,我们也可以通过两条命令来实现相同的效果:

LRANGE all:users 0 -1 //TO get all usernames

然后用HMGET对每个姓名做处理,如下所示:

HMGET user:junior name email //TO get the name and email from a user

我们可以在 redis 网站上找到命令文档.

今天就到此为止.

第 8 段(可获 1.14 积分)

文章评论