В этом посте мы поговорим о команде Redis SORT.
Redis предоставляет команду SORT, которую мы можем использовать для извлечения или сохранения отсортированных значений из LIST, SET или ZSET.
В простейшей форме мы можем использовать команду над KEY, как в примере ниже:
|
1
|
SORT numbers_list |
Это позволит отсортировать значения, содержащиеся в ключе, и вернуть их. Команда сортирует значения по номерам. Итак, допустим, у нас есть список со следующими значениями:
|
1
|
1, 110, 5 |
Команда выше вернется
|
1
|
1 5 110 |
Мы можем указать сортировку значений по алфавиту, используя модификатор ALPHA. Есть ряд модификаторов. Мы рассмотрим некоторые из них в примерах ниже. В примерах будет использоваться API джедаев.
Для наших примеров давайте рассмотрим, что у нас есть система управления идеями. У нас есть список, содержащий все имена пользователей из системы:
|
1
|
all:users [junior, francisco, ribeiro, user4] |
И для каждого имени пользователя будет хеш, содержащий информацию о пользователе:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
|
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 для нашего примера:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
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); }} |
Давайте посмотрим на пример кода ниже:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
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 System.out.println(jedis.sort("all:users")); //[ribeiro, francisco, junior, user4] //[2]sorting the username alpha //jedis sort method receives a SortingParams instance for modifiers System.out.println(jedis.sort("all:users", new SortingParams().alpha())); //[francisco, junior, ribeiro, user4] }} |
В приведенном выше примере мы сортируем ключ « все: пользователи ». С первой попытки, похоже, сортировка выполнена неправильно, поскольку сортировка по умолчанию учитывает числа. Во втором примере мы используем модификатор ALPHA . Мы можем сделать это, используя перегруженную версию метода sort. Он получает экземпляр класса SortingParams. В этом случае мы видим, что имена пользователей отсортированы правильно.
Приятной особенностью команды SORT является то, что мы можем сортировать список, используя внешние значения, значения в других ключах. В приведенном ниже примере мы отсортируем ключ all: users по количеству идей, предложенных пользователем. Это можно сделать с помощью модификатора « BY », который получает шаблон используемых ключей. Давайте посмотрим наш пример ниже:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
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())); }} |
Во втором примере мы сортируем имена пользователей по внешнему значению, в нашем случае по полю « num_ideas ». Так как в этом случае мы сортируем по хеш-полю, мы использовали следующий шаблон « user: * -> num_ideas «. С этим шаблоном мы говорим искать ключ « user: * », где этот «*» будет заменен значением из списка. Поскольку это хеш, нам нужно сообщить поле, мы делаем это, используя шаблон « -> fieldname «. Если бы мы сортировали по строковому ключу, мы могли бы использовать следующий шаблон « num_ideas_ * », учитывая, что был ключ для хранения количества идей для каждого пользователя.
При первом вызове он извлекает значения, сортируя их ASC , мы также можем сказать redis, что нужно отсортировать его DESC с помощью модификатора DESC. С jedis BY и DESC являются методы из SortingParams. Поскольку все методы возвращают экземпляр, мы можем связать все вызовы, что облегчает чтение кода.
С помощью команды SORT мы также можем получить значения из внешнего ключа или поля из внешнего хеша. Мы можем сделать это, используя модификатор GET , и мы можем использовать его много раз. Давайте посмотрим несколько примеров этого модификатора ниже:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
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] }} |
В приведенном выше коде мы видим использование модификатора GET , чтобы вернуть хеш-поле, мы можем использовать шаблон, похожий на тот, который мы использовали в модификаторе BY. В первом мы просто возвращаем имя, как мы уже говорили, мы можем использовать GET много раз, во втором мы получаем имя и адрес электронной почты от пользователя. Мы также можем получить значение для ключа, который был отсортирован, используя специальный шаблон «#». Метод get, получает vararg, поэтому мы можем передать все внешние ключи, из которых мы хотим получить значение.
Еще одна вещь, которую мы можем сделать, это сохранить результат сортировки в ключе. Это полезно в тех случаях, когда мы хотим кэшировать результат сортировки, мы можем указать ключ dest для команды сортировки. Результат будет сохранен в виде списка.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
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] }} |
Одна очень полезная особенность команды SORT заключается в том, что мы можем использовать ее только для получения значений из связанных ключей. Существует модификатор, указывающий, что не следует сортировать NOSORT
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
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, нам понадобятся как минимум две команды, чтобы сделать то же самое:
|
1
|
LRANGE all:users 0 -1 //TO get all usernames |
а затем для каждого имени пользователя вызовите hmget для каждого, как показано ниже
|
1
|
HMGET user:junior name email //TO get the name and email from a user |
- Мы можем найти документацию команды на сайте redis .