Skip to content

Commit e97fdad

Browse files
Merge pull request #1313 from redis/DOC-4952-python-scan-iter
DOC-4952 Python scan iterators page
2 parents ae9c381 + f1d6fa9 commit e97fdad

File tree

1 file changed

+110
-0
lines changed

1 file changed

+110
-0
lines changed
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
---
2+
categories:
3+
- docs
4+
- develop
5+
- stack
6+
- oss
7+
- rs
8+
- rc
9+
- oss
10+
- kubernetes
11+
- clients
12+
description: Iterate through results from `SCAN`, `HSCAN`, etc.
13+
linkTitle: Scan iteration
14+
title: Scan iteration
15+
weight: 5
16+
---
17+
18+
Redis has a small family of related commands that retrieve
19+
keys and, in some cases, their associated values:
20+
21+
- [`SCAN`]({{< relref "/commands/scan" >}}) retrieves keys
22+
from the main Redis keyspace.
23+
- [`HSCAN`]({{< relref "/commands/hscan" >}}) retrieves keys and optionally,
24+
their values from a
25+
[hash]({{< relref "/develop/data-types/hashes" >}}) object.
26+
- [`SSCAN`]({{< relref "/commands/sscan" >}}) retrieves keys from a
27+
[set]({{< relref "/develop/data-types/sets" >}}) object.
28+
- [`ZSCAN`]({{< relref "/commands/zscan" >}}) retrieves keys and their score values from a
29+
[sorted set]({{< relref "/develop/data-types/sorted-sets" >}}) object.
30+
31+
These commands can potentially return large numbers of results, so Redis
32+
provides a paging mechanism to access the results in small, separate batches.
33+
With the basic commands, you must maintain a cursor value in your code
34+
to keep track of the current page. As a convenient alternative, `redis-py`
35+
also lets you access the results using an
36+
[iterator](https://docs.python.org/3/glossary.html#term-iterable).
37+
This handles the paging transparently, so you simply need to process
38+
the items it returns one-by-one in a `for` loop or pass the iterator
39+
object itself in place of a
40+
[sequence](https://docs.python.org/3/glossary.html#term-sequence).
41+
42+
Each of the commands has its own equivalent iterator. The following example shows
43+
how to use a `SCAN` iterator on the Redis keyspace. Note that, as with the `SCAN`
44+
command, the results are not sorted into any particular order, . Also, you
45+
can pass `match`, `count`, and `_type` parameters to `scan_iter()` to constrain
46+
the set of keys it returns (see the [`SCAN`]({{< relref "/commands/scan" >}})
47+
command page for examples).
48+
49+
```py
50+
import redis
51+
52+
r = redis.Redis(decode_responses=True)
53+
54+
r.set("key:1", "a")
55+
r.set("key:2", "b")
56+
r.set("key:3", "c")
57+
r.set("key:4", "d")
58+
r.set("key:5", "e")
59+
60+
for key in r.scan_iter():
61+
print(f"Key: {key}, value: {r.get(key)}")
62+
# >>> Key: key:1, value: a
63+
# >>> Key: key:4, value: d
64+
# >>> Key: key:3, value: c
65+
# >>> Key: key:2, value: b
66+
# >>> Key: key:5, value: e
67+
```
68+
69+
The iterators for the other commands are also named with `_iter()` after
70+
the name of the basic command (`hscan_iter()`, `sscan_iter()`, and `zscan_iter()`).
71+
They work in a similar way to `scan_iter()` except that you must pass a
72+
key to identify the object you want to scan. The example below shows how to
73+
iterate through the items in a sorted set using `zscan_iter()`.
74+
75+
```py
76+
r.zadd("battles", mapping={
77+
"hastings": 1066,
78+
"agincourt": 1415,
79+
"trafalgar": 1805,
80+
"somme": 1916,
81+
})
82+
83+
for item in r.zscan_iter("battles"):
84+
print(f"Key: {item[0]}, value: {int(item[1])}")
85+
# >>> Key: hastings, value: 1066
86+
# >>> Key: agincourt, value: 1415
87+
# >>> Key: trafalgar, value: 1805
88+
# >>> Key: somme, value: 1916
89+
```
90+
91+
Note that in this case, the item returned by the iterator is a
92+
[tuple](https://docs.python.org/3/tutorial/datastructures.html#tuples-and-sequences)
93+
with two elements for the key and score. By default, `hscan_iter()`
94+
also returns a 2-tuple for the key and value, but you can
95+
pass a value of `True` for the `no_values` parameter to retrieve just
96+
the keys:
97+
98+
```py
99+
r.hset("details", mapping={
100+
"name": "Mr Benn",
101+
"address": "52 Festive Road",
102+
"hobbies": "Cosplay"
103+
})
104+
105+
for key in r.hscan_iter("details", no_values=True):
106+
print(f"Key: {key}, value: {r.hget("details", key)}")
107+
# >>> Key: name, value: Mr Benn
108+
# >>> Key: address, value: 52 Festive Road
109+
# >>> Key: hobbies, value: Cosplay
110+
```

0 commit comments

Comments
 (0)