Redis, Part 2: Lists
Welcome to Part 2 in my series of posts about Redis, a key-value database and open source project created by Salvatore Sanfilippo. In Part 1, we discussed some basic Redis commands: getting and setting values, testing for key existence, and incrementing and decrementing values. Standard stuff in the world of key-value databases. This time, we’ll explore something more interesting: lists.
(If you haven’t read Part 1 yet, please do so before continuing.)
A list is an ordered collection of values. Think of it like an array in your favorite programming language. You can insert values at the beginning (left) and end (right) of the list, retrieve single and ranges of elements, and delete elements.
To follow along with these examples, start the Redis server and then connect with telnet, just like we did in part 1.
Inserting Elements
Let’s create a new list:
% LPUSH vowels 1
% a
+OK
Inserting an element is called pushing. Because the key vowels
doesn’t exist yet, a new list is created with a single value, a
. Let’s add two more values to the list, this time at the end:
% RPUSH vowels 1
% e
+OK
% RPUSH vowels 1
% i
+OK
We’ve pushed three values into our list; let’s make sure Redis agrees.
% LLEN vowels
:3
Now that we have some values in the list, how do we get them back out?
Retrieving Elements
Redis has a few commands for retrieving list elements; which command to use depends on how many elements we wish to retrieve.
We can get a single value back with the LINDEX
command. Lists in Redis are zero-based, so the first element of a list has index 0, the second has index 1, and so on. So far our list has values a
, e
, and i
. Let’s get each by its index.
% LINDEX vowels 0
$1
a
% LINDEX vowels 1
$1
e
% LINDEX vowels 2
$1
i
If we try to get the value at an index that doesn’t exists, Redis returns a null value.
% LINDEX vowels 3
$-1
Suppose we want the last (right-most) value in the list, but we don’t know how long it is. Using a negative index, we can get elements starting at the end of the list:
% LINDEX vowels -1
$1
i
% LINDEX vowels -2
$1
e
We can retrieve more than one value using the LRANGE
command, which takes three arguments: the key, the start index, and the end index. To get the first two elements in the list:
% LRANGE vowels 0 1
*2
$1
a
$1
e
(The first line reads *2
, which means two elements are being returned.)
LRANGE
accepts negative indices, just like LINDEX
. Let’s get all the elements in the list:
% LRANGE vowels 0 -1
*3
$1
a
$1
e
$1
i
By making both indices negative, we can get the last two values out of the list:
% LRANGE vowels -2 -1
*2
$1
e
$1
i
Deleting Elements
Suppose we executed a few more commands and now vowels
looks like this: y, j, u, x, o, j, a, e, i, x, j, j
. Let’s clean it up by removing the extra elements.
First, let’s delete the y
at index 0. One way is to use the LPOP
command. LPOP
removes and returns the first element of the list:
% LPOP vowels
$1
y
We can also RPOP
, which does the same thing to the last element of the list.
Another option is to trim the list to a smaller version of itself. We can do this with the LTRIM
command. LTRIM
works exactly like LRANGE
except instead of returning the range Redis overwrites the key with it:
% LTRIM vowels 1 -1
+OK
This command sets vowels
to be the range starting at index 1 and ending at the last element. vowels
now contains these elements: u, x, o, j, a, e, i, x, j, j
.
Let’s get rid of those j
s using the LREM
command. LREM
takes three arguments: a key to operate on, the number of matching elements to remove, and the value to remove1.
Let’s remove the first j
:
% LREM vowels 1 1
% j
:1
The first 1
tells Redis to start searching at the first element and to remove one instance of j
. (The second 1
is the size in bytes of the value for which to search.) Redis responds with :1
, the number of elements removed.
Let’s remove two more j
s, this time from the end of the list:
% LREM vowels -2 1
% j
:2
The -2
tells Redis to remove two elements and, because of the negative sign, to search starting at the end of the list. Two elements have been removed, so Redis says :2
.
Now our list is u, x, o, a, e, i, x
. Let’s remove all of the x
s in one go:
% LREM vowels 0 1
% x
:2
By sending 0
as the second argument we’re telling Redis to remove all x
elements.
Sorting
We have a complete list of vowels–u, o, a, e, i
–but they’re in the wrong order. Let’s get a sorted list of vowels:
% SORT vowels ALPHA
*5
$1
a
$1
e
$1
i
$1
o
$1
u
SORT
is a powerful command with many options and we’ll cover it later in greater detail. For now, here are a couple more things you can do with SORT
.
Sort in the opposite direction:
% SORT vowels ALPHA DESC
*5
$1
u
$1
o
$1
i
$1
e
$1
a
Limit the returned list to 3 elements, starting at index 1:
% SORT vowels LIMIT 1 3 ALPHA
*3
$1
e
$1
i
$1
o
So far, we’ve only had a taste of why Redis is so exciting. Next time we’ll look at sets and things will really pick up.
-
Redis can’t remove an element by index. There will always be a delay between when a command is sent and executed–during that delay, the list could be modified by another client and the index would then reference the wrong element.