docs
0
# Hash Operations
1
2
Redis hash data type operations providing a mapping between string fields and string values. Hashes are perfect for representing objects and can hold up to 2^32 - 1 field-value pairs, making them ideal for storing structured data like user profiles, configuration settings, and object attributes.
3
4
## Capabilities
5
6
### Basic Hash Operations
7
8
Core hash manipulation functions for setting, getting, and managing field-value pairs.
9
10
```python { .api }
11
def hset(
12
self,
13
name: KeyT,
14
key: Optional[FieldT] = None,
15
value: Optional[EncodableT] = None,
16
mapping: Optional[Mapping[AnyFieldT, EncodableT]] = None
17
) -> ResponseT: ...
18
19
def hget(self, name: KeyT, key: FieldT) -> Optional[bytes]: ...
20
21
def hmget(self, name: KeyT, keys: Iterable[FieldT]) -> List[Optional[bytes]]: ...
22
23
def hmset(self, name: KeyT, mapping: Mapping[AnyFieldT, EncodableT]) -> ResponseT: ...
24
25
def hgetall(self, name: KeyT) -> Dict[bytes, bytes]: ...
26
27
def hdel(self, name: KeyT, *keys: FieldT) -> ResponseT: ...
28
29
def hexists(self, name: KeyT, key: FieldT) -> ResponseT: ...
30
31
def hlen(self, name: KeyT) -> ResponseT: ...
32
```
33
34
### Hash Field Operations
35
36
Functions for working with hash fields including listing keys, values, and field information.
37
38
```python { .api }
39
def hkeys(self, name: KeyT) -> ResponseT: ...
40
41
def hvals(self, name: KeyT) -> ResponseT: ...
42
43
def hstrlen(self, name: KeyT, key: FieldT) -> ResponseT: ...
44
45
def hsetnx(self, name: KeyT, key: FieldT, value: EncodableT) -> ResponseT: ...
46
47
def hrandfield(
48
self,
49
key: KeyT,
50
count: Optional[int] = None,
51
withvalues: bool = False
52
) -> Union[Optional[bytes], List[bytes], List[Union[bytes, Tuple[bytes, bytes]]]]: ...
53
```
54
55
### Hash Numeric Operations
56
57
Numeric operations for hash fields including increment and decrement operations.
58
59
```python { .api }
60
def hincrby(self, name: KeyT, key: FieldT, amount: int = 1) -> ResponseT: ...
61
62
def hincrbyfloat(self, name: KeyT, key: FieldT, amount: float = 1.0) -> ResponseT: ...
63
```
64
65
### Hash Scanning
66
67
Iterator functions for efficiently traversing hash fields and values.
68
69
```python { .api }
70
def hscan(
71
self,
72
name: KeyT,
73
cursor: int = 0,
74
match: Optional[PatternT] = None,
75
count: Optional[int] = None
76
) -> ResponseT: ...
77
78
def hscan_iter(
79
self,
80
name: KeyT,
81
match: Optional[PatternT] = None,
82
count: Optional[int] = None
83
) -> Iterator[Tuple[bytes, bytes]]: ...
84
```
85
86
## Usage Examples
87
88
### Basic Hash Operations
89
90
```python
91
import fakeredis
92
93
client = fakeredis.FakeRedis()
94
95
# Set individual field
96
client.hset('user:1', 'name', 'Alice')
97
client.hset('user:1', 'email', 'alice@example.com')
98
client.hset('user:1', 'age', '30')
99
100
# Set multiple fields at once
101
client.hset('user:2', mapping={
102
'name': 'Bob',
103
'email': 'bob@example.com',
104
'age': '25'
105
})
106
107
# Get individual field
108
name = client.hget('user:1', 'name')
109
print(name.decode()) # 'Alice'
110
111
# Get multiple fields
112
values = client.hmget('user:1', ['name', 'email', 'age'])
113
for value in values:
114
if value:
115
print(value.decode())
116
117
# Get all fields and values
118
user_data = client.hgetall('user:1')
119
for field, value in user_data.items():
120
print(f"{field.decode()}: {value.decode()}")
121
```
122
123
### Hash Manipulation
124
125
```python
126
import fakeredis
127
128
client = fakeredis.FakeRedis()
129
130
# Initialize user profile
131
client.hset('profile:alice', mapping={
132
'name': 'Alice Johnson',
133
'department': 'Engineering',
134
'level': '5',
135
'salary': '95000'
136
})
137
138
# Check if field exists
139
has_salary = client.hexists('profile:alice', 'salary')
140
print(has_salary) # True
141
142
# Get number of fields
143
field_count = client.hlen('profile:alice')
144
print(field_count) # 4
145
146
# Get all field names
147
fields = client.hkeys('profile:alice')
148
for field in fields:
149
print(field.decode())
150
151
# Get all values
152
values = client.hvals('profile:alice')
153
for value in values:
154
print(value.decode())
155
156
# Delete fields
157
deleted_count = client.hdel('profile:alice', 'salary', 'level')
158
print(deleted_count) # 2
159
```
160
161
### Conditional Operations
162
163
```python
164
import fakeredis
165
166
client = fakeredis.FakeRedis()
167
168
# Set field only if it doesn't exist
169
result = client.hsetnx('config:app', 'debug_mode', 'false')
170
print(result) # 1 if set, 0 if field already exists
171
172
# Try to set again (will fail)
173
result = client.hsetnx('config:app', 'debug_mode', 'true')
174
print(result) # 0 (field already exists)
175
176
# Get string length of field value
177
client.hset('user:profile', 'bio', 'Software engineer with 10 years experience')
178
bio_length = client.hstrlen('user:profile', 'bio')
179
print(bio_length) # Length of the bio string
180
```
181
182
### Numeric Operations
183
184
```python
185
import fakeredis
186
187
client = fakeredis.FakeRedis()
188
189
# Initialize counters
190
client.hset('stats:page', mapping={
191
'views': '100',
192
'likes': '25',
193
'rating': '4.5'
194
})
195
196
# Increment integer field
197
new_views = client.hincrby('stats:page', 'views', 1)
198
print(new_views) # 101
199
200
# Increment by larger amount
201
new_views = client.hincrby('stats:page', 'views', 50)
202
print(new_views) # 151
203
204
# Increment float field
205
new_rating = client.hincrbyfloat('stats:page', 'rating', 0.1)
206
print(new_rating) # 4.6
207
208
# Handle non-existent fields (start from 0)
209
page_shares = client.hincrby('stats:page', 'shares', 1)
210
print(page_shares) # 1
211
```
212
213
### Random Field Selection
214
215
```python
216
import fakeredis
217
218
client = fakeredis.FakeRedis()
219
220
# Setup sample data
221
client.hset('inventory:store1', mapping={
222
'apples': '150',
223
'bananas': '200',
224
'oranges': '75',
225
'grapes': '300',
226
'strawberries': '45'
227
})
228
229
# Get random field
230
random_field = client.hrandfield('inventory:store1')
231
print(random_field.decode()) # Random fruit name
232
233
# Get multiple random fields
234
random_fields = client.hrandfield('inventory:store1', count=3)
235
for field in random_fields:
236
print(field.decode())
237
238
# Get random fields with values
239
random_items = client.hrandfield('inventory:store1', count=2, withvalues=True)
240
for i in range(0, len(random_items), 2):
241
field = random_items[i].decode()
242
value = random_items[i+1].decode()
243
print(f"{field}: {value}")
244
```
245
246
### Hash Scanning
247
248
```python
249
import fakeredis
250
251
client = fakeredis.FakeRedis()
252
253
# Setup large hash
254
for i in range(1000):
255
client.hset(f'large_hash', f'field_{i}', f'value_{i}')
256
257
# Scan all fields
258
cursor = 0
259
all_fields = []
260
261
while True:
262
cursor, fields = client.hscan('large_hash', cursor=cursor, count=100)
263
all_fields.extend(fields.items())
264
if cursor == 0:
265
break
266
267
print(f"Total fields scanned: {len(all_fields)}")
268
269
# Scan with pattern matching
270
matching_fields = []
271
for field, value in client.hscan_iter('large_hash', match='field_1*'):
272
matching_fields.append((field.decode(), value.decode()))
273
274
print(f"Fields matching pattern: {len(matching_fields)}")
275
```
276
277
### Pattern: Object Storage
278
279
```python
280
import fakeredis
281
import json
282
283
class UserProfile:
284
def __init__(self, client, user_id):
285
self.client = client
286
self.key = f'user:{user_id}'
287
288
def set_field(self, field, value):
289
return self.client.hset(self.key, field, value)
290
291
def get_field(self, field):
292
value = self.client.hget(self.key, field)
293
return value.decode() if value else None
294
295
def set_profile(self, **kwargs):
296
return self.client.hset(self.key, mapping=kwargs)
297
298
def get_profile(self):
299
data = self.client.hgetall(self.key)
300
return {k.decode(): v.decode() for k, v in data.items()}
301
302
def increment_field(self, field, amount=1):
303
return self.client.hincrby(self.key, field, amount)
304
305
# Usage
306
client = fakeredis.FakeRedis()
307
user = UserProfile(client, '12345')
308
309
# Set profile data
310
user.set_profile(
311
name='John Doe',
312
email='john@example.com',
313
login_count='0',
314
last_seen='2024-01-15'
315
)
316
317
# Update individual fields
318
user.set_field('status', 'active')
319
user.increment_field('login_count')
320
321
# Retrieve profile
322
profile = user.get_profile()
323
print(profile)
324
```
325
326
### Pattern: Configuration Management
327
328
```python
329
import fakeredis
330
331
class ConfigManager:
332
def __init__(self, client, app_name):
333
self.client = client
334
self.key = f'config:{app_name}'
335
336
def set_config(self, **kwargs):
337
return self.client.hset(self.key, mapping=kwargs)
338
339
def get_config(self, key=None):
340
if key:
341
value = self.client.hget(self.key, key)
342
return value.decode() if value else None
343
else:
344
config = self.client.hgetall(self.key)
345
return {k.decode(): v.decode() for k, v in config.items()}
346
347
def update_config(self, **kwargs):
348
return self.client.hset(self.key, mapping=kwargs)
349
350
def remove_config(self, *keys):
351
return self.client.hdel(self.key, *keys)
352
353
def has_config(self, key):
354
return bool(self.client.hexists(self.key, key))
355
356
# Usage
357
client = fakeredis.FakeRedis()
358
config = ConfigManager(client, 'myapp')
359
360
# Set initial configuration
361
config.set_config(
362
database_url='postgresql://localhost/myapp',
363
debug_mode='false',
364
max_connections='100',
365
timeout='30'
366
)
367
368
# Update specific settings
369
config.update_config(debug_mode='true', timeout='60')
370
371
# Check configuration
372
if config.has_config('database_url'):
373
db_url = config.get_config('database_url')
374
print(f"Database URL: {db_url}")
375
376
# Get all configuration
377
all_config = config.get_config()
378
print("Current configuration:", all_config)
379
```
380
381
### Pattern: Session Storage
382
383
```python
384
import fakeredis
385
import json
386
import time
387
388
class SessionManager:
389
def __init__(self, client, session_id):
390
self.client = client
391
self.key = f'session:{session_id}'
392
393
def set_session_data(self, **kwargs):
394
# Add timestamp
395
kwargs['last_activity'] = str(int(time.time()))
396
return self.client.hset(self.key, mapping=kwargs)
397
398
def get_session_data(self, field=None):
399
if field:
400
value = self.client.hget(self.key, field)
401
return value.decode() if value else None
402
else:
403
data = self.client.hgetall(self.key)
404
return {k.decode(): v.decode() for k, v in data.items()}
405
406
def touch_session(self):
407
return self.client.hset(self.key, 'last_activity', str(int(time.time())))
408
409
def increment_counter(self, counter_name):
410
return self.client.hincrby(self.key, counter_name, 1)
411
412
def destroy_session(self):
413
return self.client.delete(self.key)
414
415
# Usage
416
client = fakeredis.FakeRedis()
417
session = SessionManager(client, 'sess_abc123')
418
419
# Initialize session
420
session.set_session_data(
421
user_id='12345',
422
username='alice',
423
role='user',
424
page_views='0'
425
)
426
427
# Update session activity
428
session.touch_session()
429
session.increment_counter('page_views')
430
431
# Get session info
432
user_id = session.get_session_data('user_id')
433
all_data = session.get_session_data()
434
print(f"User: {user_id}, Session data: {all_data}")
435
```