In Redis, the SORT command allows us to sort lists, sets, and sorted sets.
We can have the sorted elements returned to the client, or we can store them in a separate key.
Syntax
SORT key [BY pattern] [LIMIT offset count] [GET pattern [GET pattern ...]] [ ASC | DESC] [ALPHA] [STORE destination]
The various options are explained in the following examples.
Example
Suppose we create a list:
LPUSH scores 10 8 3 7 5 12 7 0 1 9 2
Result:
(integer) 11
And let’s take a look at the list (without sorting it):
LRANGE scores 0 -1
Result:
1) "2" 2) "9" 3) "1" 4) "0" 5) "7" 6) "12" 7) "5" 8) "7" 9) "3" 10) "8" 11) "10"
Now let’s use the SORT command to change the order:
SORT scores
Result:
1) "0" 2) "1" 3) "2" 4) "3" 5) "5" 6) "7" 7) "7" 8) "8" 9) "9" 10) "10" 11) "12"
The ASC and DESC Modifiers
By default, the SORT command sorts the results in ascending order. So when using numbers, a list is sorted from small to large. We can explicitly enforce this with the ASC modifier. We can use the DESC modifier to sort from large to small.
Here’s the previous example again, but this time with the ASC modifier:
SORT scores ASC
Result:
1) "0" 2) "1" 3) "2" 4) "3" 5) "5" 6) "7" 7) "7" 8) "8" 9) "9" 10) "10" 11) "12"
We get the same result as in the previous example.
Here it is with the DESC modifier:
SORT scores DESC
Result:
1) "12" 2) "10" 3) "9" 4) "8" 5) "7" 6) "7" 7) "5" 8) "3" 9) "2" 10) "1" 11) "0"
The ALPHA Modifier
We can use the ALPHA modifier to sort string values lexicographically.
Suppose we create this list:
LPUSH pets "Tweet" "Fluffy" "Scratch" "Bark" "Fluffy" "Woof"
Result:
(integer) 6
We can look at its contents (unsorted):
LRANGE pets 0 -1
Result:
1) "Woof" 2) "Fluffy" 3) "Bark" 4) "Scratch" 5) "Fluffy" 6) "Tweet"
Now let’s use SORT to sort the contents in ascending order:
SORT pets ALPHA
Result:
1) "Bark" 2) "Fluffy" 3) "Fluffy" 4) "Scratch" 5) "Tweet" 6) "Woof"
Or we can use the ASC modifier to explicitly sort it in ascending order:
SORT pets ASC ALPHA
Result:
1) "Bark" 2) "Fluffy" 3) "Fluffy" 4) "Scratch" 5) "Tweet" 6) "Woof"
And here it is in descending order:
SORT pets DESC ALPHA
Result:
1) "Woof" 2) "Tweet" 3) "Scratch" 4) "Fluffy" 5) "Fluffy" 6) "Bark"
We can also apply the ALPHA modifier on numbers to sort them alphabetically:
SORT scores ALPHA
Result:
1) "0" 2) "1" 3) "10" 4) "12" 5) "2" 6) "3" 7) "5" 8) "7" 9) "7" 10) "8" 11) "9"
The LIMIT Modifier
We can use the LIMIT modifier to limit how many elements are returned. This modifier takes an offset amount as well as the number of elements to return from that offset.
We can specify no offset by using 0 as the offset:
SORT pets LIMIT 0 3 ASC ALPHA
Result:
1) "Bark" 2) "Fluffy" 3) "Fluffy"
And here it is with an offset:
SORT pets LIMIT 2 3 ASC ALPHA
Result:
1) "Fluffy" 2) "Scratch" 3) "Tweet"
The BY Option
We can use the BY option to sort by external keys as weights to compare instead of comparing the actual elements in the list.
Suppose we create a list like this:
LPUSH uid 1 2 3 4 5
Result:
(integer) 5
And we set the following points_* keys:
MSET points_1 500 points_2 200 points_3 300 points_4 400 points_5 100
Result:
OK
We can sort mylist by the points_* keys:
SORT uid BY points_* ASC
Result:
1) "5" 2) "2" 3) "3" 4) "4" 5) "1"
The order of the elements is reflective of the values in the points_* keys.
Here it is when using DESC for descending order:
SORT uid BY points_* DESC
Result:
1) "1" 2) "4" 3) "3" 4) "2" 5) "5"
Getting External Keys
The above technique can be handy when each list element represents a unique ID of a separate object. These objects can have their weights stored in external keys (in this case, the points_* keys), which can be used for sorting them.
We can also use the GET option of the SORT command to retrieve the external keys.
Suppose we create the following objects:
MSET user_1 "Homer" user_2 "Bart" user_3 "Marge" user_4 "Maggie" user_5 "Milhouse"
Result:
OK
We can now build on the previous example by doing the following:
SORT uid BY points_* GET user_*
Result:
1) "Milhouse" 2) "Bart" 3) "Marge" 4) "Maggie" 5) "Homer"
Here it is in descending order:
SORT uid BY points_* GET user_* DESC
Result:
1) "Homer" 2) "Maggie" 3) "Marge" 4) "Bart" 5) "Milhouse"
We can also use another GET with the # pattern to get the other element:
SORT uid BY points_* GET user_* GET #
Result:
1) "Milhouse" 2) "5" 3) "Bart" 4) "2" 5) "Marge" 6) "3" 7) "Maggie" 8) "4" 9) "Homer" 10) "1"
For hash fields, we can use the following syntax for BY and GET:
SORT points BY weight_*->fieldname GET object_*->fieldname
Sorting by a Non-Existent Key
We can use the BY option to sort by a key that doesn’t exist. When we do this, it skips the sorting altogether:
SORT points BY nonexistentkey
Result:
1) "3" 2) "2" 3) "4" 4) "1" 5) "5"
However, when we do this, the ASC and DESC modifiers still work:
SORT points BY nonexistentkey DESC
Result:
1) "5" 2) "1" 3) "4" 4) "2" 5) "3"
The STORE Option
We can use the STORE option to store the results of SORT to a key.
Example:
SORT pets ALPHA STORE pets_sorted
Result:
(integer) 6
Now we can access the sorted results by accessing the new key without having to perform another SORT operation:
LRANGE pets_sorted 0 -1
Result:
1) "Bark" 2) "Fluffy" 3) "Fluffy" 4) "Scratch" 5) "Tweet" 6) "Woof"