Redis hashes
Introduction to Redis hashes
Redis hashes are record types structured as collections of field-value pairs.
You can use hashes to represent basic objects and to store groupings of counters, among other things.
>_ Redis CLI
> hset bike:1 model Deimos brand Ergonom type 'Enduro bikes' price 4972
(integer) 4
> hget bike:1 model
"Deimos"
> hget bike:1 price
"4972"
> hgetall bike:1
1) "model"
2) "Deimos"
3) "brand"
4) "Ergonom"
5) "type"
6) "Enduro bikes"
7) "price"
8) "4972"
Node.js
import { createClient } from 'redis' ;
const client = createClient ();
client . on ( 'error' , err => console . log ( 'Redis Client Error' , err ));
await client . connect ();
const fieldsAdded = await client . hSet (
'bike:1' ,
{
model : 'Deimos' ,
brand : 'Ergonom' ,
type : 'Enduro bikes' ,
price : 4972 ,
},
)
console . log ( `Number of fields were added: ${ fieldsAdded } ` );
// Number of fields were added: 4
const model = await client . hGet ( 'bike:1' , 'model' );
console . log ( `Model: ${ model } ` );
// Model: Deimos
const price = await client . hGet ( 'bike:1' , 'price' );
console . log ( `Price: ${ price } ` );
// Price: 4972
const bike = await client . hGetAll ( 'bike:1' );
console . log ( bike );
// {
// model: 'Deimos',
// brand: 'Ergonom',
// type: 'Enduro bikes',
// price: '4972'
// }
const fields = await client . hmGet ( 'bike:1' , [ 'model' , 'price' ]);
console . log ( fields );
// [ 'Deimos', '4972' ]
let newPrice = await client . hIncrBy ( 'bike:1' , 'price' , 100 );
console . log ( newPrice );
// 5072
newPrice = await client . hIncrBy ( 'bike:1' , 'price' , - 100 );
console . log ( newPrice );
// 4972
let rides = await client . hIncrBy ( 'bike:1:stats' , 'rides' , 1 );
console . log ( rides );
// 1
rides = await client . hIncrBy ( 'bike:1:stats' , 'rides' , 1 );
console . log ( rides );
// 2
rides = await client . hIncrBy ( 'bike:1:stats' , 'rides' , 1 );
console . log ( rides );
// 3
let crashes = await client . hIncrBy ( 'bike:1:stats' , 'crashes' , 1 );
console . log ( crashes );
// 1
let owners = await client . hIncrBy ( 'bike:1:stats' , 'owners' , 1 );
console . log ( owners );
// 1
rides = await client . hGet ( 'bike:1:stats' , 'rides' );
console . log ( `Total rides: ${ rides } ` );
// Total rides: 3
const stats = await client . hmGet ( 'bike:1:stats' , [ 'crashes' , 'owners' ]);
console . log ( `Bike stats: crashes= ${ stats [ 0 ] } , owners= ${ stats [ 1 ] } ` );
// Bike stats: crashes=1, owners=1
await client . quit ();
Copied!
Python
import redis
r = redis . Redis ( decode_responses = True )
res1 = r . hset (
"bike:1" ,
mapping = {
"model" : "Deimos" ,
"brand" : "Ergonom" ,
"type" : "Enduro bikes" ,
"price" : 4972 ,
},
)
print ( res1 )
# >>> 4
res2 = r . hget ( "bike:1" , "model" )
print ( res2 )
# >>> 'Deimos'
res3 = r . hget ( "bike:1" , "price" )
print ( res3 )
# >>> '4972'
res4 = r . hgetall ( "bike:1" )
print ( res4 )
# >>> {'model': 'Deimos', 'brand': 'Ergonom', 'type': 'Enduro bikes', 'price': '4972'}
res5 = r . hmget ( "bike:1" , [ "model" , "price" ])
print ( res5 )
# >>> ['Deimos', '4972']
res6 = r . hincrby ( "bike:1" , "price" , 100 )
print ( res6 )
# >>> 5072
res7 = r . hincrby ( "bike:1" , "price" , - 100 )
print ( res7 )
# >>> 4972
res11 = r . hincrby ( "bike:1:stats" , "rides" , 1 )
print ( res11 )
# >>> 1
res12 = r . hincrby ( "bike:1:stats" , "rides" , 1 )
print ( res12 )
# >>> 2
res13 = r . hincrby ( "bike:1:stats" , "rides" , 1 )
print ( res13 )
# >>> 3
res14 = r . hincrby ( "bike:1:stats" , "crashes" , 1 )
print ( res14 )
# >>> 1
res15 = r . hincrby ( "bike:1:stats" , "owners" , 1 )
print ( res15 )
# >>> 1
res16 = r . hget ( "bike:1:stats" , "rides" )
print ( res16 )
# >>> 3
res17 = r . hmget ( "bike:1:stats" , [ "crashes" , "owners" ])
print ( res17 )
# >>> ['1', '1']
Copied!
While hashes are handy to represent objects , actually the number of fields you can
put inside a hash has no practical limits (other than available memory), so you can use
hashes in many different ways inside your application.
The command HSET
sets multiple fields of the hash, while HGET
retrieves
a single field. HMGET
is similar to HGET
but returns an array of values:
>_ Redis CLI
> hmget bike:1 model price no-such-field
1) "Deimos"
2) "4972"
3) (nil)
Node.js
import { createClient } from 'redis' ;
const client = createClient ();
client . on ( 'error' , err => console . log ( 'Redis Client Error' , err ));
await client . connect ();
const fieldsAdded = await client . hSet (
'bike:1' ,
{
model : 'Deimos' ,
brand : 'Ergonom' ,
type : 'Enduro bikes' ,
price : 4972 ,
},
)
console . log ( `Number of fields were added: ${ fieldsAdded } ` );
// Number of fields were added: 4
const model = await client . hGet ( 'bike:1' , 'model' );
console . log ( `Model: ${ model } ` );
// Model: Deimos
const price = await client . hGet ( 'bike:1' , 'price' );
console . log ( `Price: ${ price } ` );
// Price: 4972
const bike = await client . hGetAll ( 'bike:1' );
console . log ( bike );
// {
// model: 'Deimos',
// brand: 'Ergonom',
// type: 'Enduro bikes',
// price: '4972'
// }
const fields = await client . hmGet ( 'bike:1' , [ 'model' , 'price' ]);
console . log ( fields );
// [ 'Deimos', '4972' ]
let newPrice = await client . hIncrBy ( 'bike:1' , 'price' , 100 );
console . log ( newPrice );
// 5072
newPrice = await client . hIncrBy ( 'bike:1' , 'price' , - 100 );
console . log ( newPrice );
// 4972
let rides = await client . hIncrBy ( 'bike:1:stats' , 'rides' , 1 );
console . log ( rides );
// 1
rides = await client . hIncrBy ( 'bike:1:stats' , 'rides' , 1 );
console . log ( rides );
// 2
rides = await client . hIncrBy ( 'bike:1:stats' , 'rides' , 1 );
console . log ( rides );
// 3
let crashes = await client . hIncrBy ( 'bike:1:stats' , 'crashes' , 1 );
console . log ( crashes );
// 1
let owners = await client . hIncrBy ( 'bike:1:stats' , 'owners' , 1 );
console . log ( owners );
// 1
rides = await client . hGet ( 'bike:1:stats' , 'rides' );
console . log ( `Total rides: ${ rides } ` );
// Total rides: 3
const stats = await client . hmGet ( 'bike:1:stats' , [ 'crashes' , 'owners' ]);
console . log ( `Bike stats: crashes= ${ stats [ 0 ] } , owners= ${ stats [ 1 ] } ` );
// Bike stats: crashes=1, owners=1
await client . quit ();
Copied!
Python
import redis
r = redis . Redis ( decode_responses = True )
res1 = r . hset (
"bike:1" ,
mapping = {
"model" : "Deimos" ,
"brand" : "Ergonom" ,
"type" : "Enduro bikes" ,
"price" : 4972 ,
},
)
print ( res1 )
# >>> 4
res2 = r . hget ( "bike:1" , "model" )
print ( res2 )
# >>> 'Deimos'
res3 = r . hget ( "bike:1" , "price" )
print ( res3 )
# >>> '4972'
res4 = r . hgetall ( "bike:1" )
print ( res4 )
# >>> {'model': 'Deimos', 'brand': 'Ergonom', 'type': 'Enduro bikes', 'price': '4972'}
res5 = r . hmget ( "bike:1" , [ "model" , "price" ])
print ( res5 )
# >>> ['Deimos', '4972']
res6 = r . hincrby ( "bike:1" , "price" , 100 )
print ( res6 )
# >>> 5072
res7 = r . hincrby ( "bike:1" , "price" , - 100 )
print ( res7 )
# >>> 4972
res11 = r . hincrby ( "bike:1:stats" , "rides" , 1 )
print ( res11 )
# >>> 1
res12 = r . hincrby ( "bike:1:stats" , "rides" , 1 )
print ( res12 )
# >>> 2
res13 = r . hincrby ( "bike:1:stats" , "rides" , 1 )
print ( res13 )
# >>> 3
res14 = r . hincrby ( "bike:1:stats" , "crashes" , 1 )
print ( res14 )
# >>> 1
res15 = r . hincrby ( "bike:1:stats" , "owners" , 1 )
print ( res15 )
# >>> 1
res16 = r . hget ( "bike:1:stats" , "rides" )
print ( res16 )
# >>> 3
res17 = r . hmget ( "bike:1:stats" , [ "crashes" , "owners" ])
print ( res17 )
# >>> ['1', '1']
Copied!
There are commands that are able to perform operations on individual fields
as well, like HINCRBY
:
>_ Redis CLI
> hincrby bike:1 price 100
(integer) 5072
> hincrby bike:1 price -100
(integer) 4972
Node.js
import { createClient } from 'redis' ;
const client = createClient ();
client . on ( 'error' , err => console . log ( 'Redis Client Error' , err ));
await client . connect ();
const fieldsAdded = await client . hSet (
'bike:1' ,
{
model : 'Deimos' ,
brand : 'Ergonom' ,
type : 'Enduro bikes' ,
price : 4972 ,
},
)
console . log ( `Number of fields were added: ${ fieldsAdded } ` );
// Number of fields were added: 4
const model = await client . hGet ( 'bike:1' , 'model' );
console . log ( `Model: ${ model } ` );
// Model: Deimos
const price = await client . hGet ( 'bike:1' , 'price' );
console . log ( `Price: ${ price } ` );
// Price: 4972
const bike = await client . hGetAll ( 'bike:1' );
console . log ( bike );
// {
// model: 'Deimos',
// brand: 'Ergonom',
// type: 'Enduro bikes',
// price: '4972'
// }
const fields = await client . hmGet ( 'bike:1' , [ 'model' , 'price' ]);
console . log ( fields );
// [ 'Deimos', '4972' ]
let newPrice = await client . hIncrBy ( 'bike:1' , 'price' , 100 );
console . log ( newPrice );
// 5072
newPrice = await client . hIncrBy ( 'bike:1' , 'price' , - 100 );
console . log ( newPrice );
// 4972
let rides = await client . hIncrBy ( 'bike:1:stats' , 'rides' , 1 );
console . log ( rides );
// 1
rides = await client . hIncrBy ( 'bike:1:stats' , 'rides' , 1 );
console . log ( rides );
// 2
rides = await client . hIncrBy ( 'bike:1:stats' , 'rides' , 1 );
console . log ( rides );
// 3
let crashes = await client . hIncrBy ( 'bike:1:stats' , 'crashes' , 1 );
console . log ( crashes );
// 1
let owners = await client . hIncrBy ( 'bike:1:stats' , 'owners' , 1 );
console . log ( owners );
// 1
rides = await client . hGet ( 'bike:1:stats' , 'rides' );
console . log ( `Total rides: ${ rides } ` );
// Total rides: 3
const stats = await client . hmGet ( 'bike:1:stats' , [ 'crashes' , 'owners' ]);
console . log ( `Bike stats: crashes= ${ stats [ 0 ] } , owners= ${ stats [ 1 ] } ` );
// Bike stats: crashes=1, owners=1
await client . quit ();
Copied!
Python
import redis
r = redis . Redis ( decode_responses = True )
res1 = r . hset (
"bike:1" ,
mapping = {
"model" : "Deimos" ,
"brand" : "Ergonom" ,
"type" : "Enduro bikes" ,
"price" : 4972 ,
},
)
print ( res1 )
# >>> 4
res2 = r . hget ( "bike:1" , "model" )
print ( res2 )
# >>> 'Deimos'
res3 = r . hget ( "bike:1" , "price" )
print ( res3 )
# >>> '4972'
res4 = r . hgetall ( "bike:1" )
print ( res4 )
# >>> {'model': 'Deimos', 'brand': 'Ergonom', 'type': 'Enduro bikes', 'price': '4972'}
res5 = r . hmget ( "bike:1" , [ "model" , "price" ])
print ( res5 )
# >>> ['Deimos', '4972']
res6 = r . hincrby ( "bike:1" , "price" , 100 )
print ( res6 )
# >>> 5072
res7 = r . hincrby ( "bike:1" , "price" , - 100 )
print ( res7 )
# >>> 4972
res11 = r . hincrby ( "bike:1:stats" , "rides" , 1 )
print ( res11 )
# >>> 1
res12 = r . hincrby ( "bike:1:stats" , "rides" , 1 )
print ( res12 )
# >>> 2
res13 = r . hincrby ( "bike:1:stats" , "rides" , 1 )
print ( res13 )
# >>> 3
res14 = r . hincrby ( "bike:1:stats" , "crashes" , 1 )
print ( res14 )
# >>> 1
res15 = r . hincrby ( "bike:1:stats" , "owners" , 1 )
print ( res15 )
# >>> 1
res16 = r . hget ( "bike:1:stats" , "rides" )
print ( res16 )
# >>> 3
res17 = r . hmget ( "bike:1:stats" , [ "crashes" , "owners" ])
print ( res17 )
# >>> ['1', '1']
Copied!
You can find the full list of hash commands in the documentation .
It is worth noting that small hashes (i.e., a few elements with small values) are
encoded in special way in memory that make them very memory efficient.
Basic commands
HSET
sets the value of one or more fields on a hash.
HGET
returns the value at a given field.
HMGET
returns the values at one or more given fields.
HINCRBY
increments the value at a given field by the integer provided.
See the complete list of hash commands .
Examples
Store counters for the number of times bike:1 has been ridden, has crashed, or has changed owners:
>_ Redis CLI
> HINCRBY bike:1:stats rides 1
(integer) 1
> HINCRBY bike:1:stats rides 1
(integer) 2
> HINCRBY bike:1:stats rides 1
(integer) 3
> HINCRBY bike:1:stats crashes 1
(integer) 1
> HINCRBY bike:1:stats owners 1
(integer) 1
> HGET bike:1:stats rides
"3"
> HMGET bike:1:stats owners crashes
1) "1"
2) "1"
Node.js
import { createClient } from 'redis' ;
const client = createClient ();
client . on ( 'error' , err => console . log ( 'Redis Client Error' , err ));
await client . connect ();
const fieldsAdded = await client . hSet (
'bike:1' ,
{
model : 'Deimos' ,
brand : 'Ergonom' ,
type : 'Enduro bikes' ,
price : 4972 ,
},
)
console . log ( `Number of fields were added: ${ fieldsAdded } ` );
// Number of fields were added: 4
const model = await client . hGet ( 'bike:1' , 'model' );
console . log ( `Model: ${ model } ` );
// Model: Deimos
const price = await client . hGet ( 'bike:1' , 'price' );
console . log ( `Price: ${ price } ` );
// Price: 4972
const bike = await client . hGetAll ( 'bike:1' );
console . log ( bike );
// {
// model: 'Deimos',
// brand: 'Ergonom',
// type: 'Enduro bikes',
// price: '4972'
// }
const fields = await client . hmGet ( 'bike:1' , [ 'model' , 'price' ]);
console . log ( fields );
// [ 'Deimos', '4972' ]
let newPrice = await client . hIncrBy ( 'bike:1' , 'price' , 100 );
console . log ( newPrice );
// 5072
newPrice = await client . hIncrBy ( 'bike:1' , 'price' , - 100 );
console . log ( newPrice );
// 4972
let rides = await client . hIncrBy ( 'bike:1:stats' , 'rides' , 1 );
console . log ( rides );
// 1
rides = await client . hIncrBy ( 'bike:1:stats' , 'rides' , 1 );
console . log ( rides );
// 2
rides = await client . hIncrBy ( 'bike:1:stats' , 'rides' , 1 );
console . log ( rides );
// 3
let crashes = await client . hIncrBy ( 'bike:1:stats' , 'crashes' , 1 );
console . log ( crashes );
// 1
let owners = await client . hIncrBy ( 'bike:1:stats' , 'owners' , 1 );
console . log ( owners );
// 1
rides = await client . hGet ( 'bike:1:stats' , 'rides' );
console . log ( `Total rides: ${ rides } ` );
// Total rides: 3
const stats = await client . hmGet ( 'bike:1:stats' , [ 'crashes' , 'owners' ]);
console . log ( `Bike stats: crashes= ${ stats [ 0 ] } , owners= ${ stats [ 1 ] } ` );
// Bike stats: crashes=1, owners=1
await client . quit ();
Copied!
Python
import redis
r = redis . Redis ( decode_responses = True )
res1 = r . hset (
"bike:1" ,
mapping = {
"model" : "Deimos" ,
"brand" : "Ergonom" ,
"type" : "Enduro bikes" ,
"price" : 4972 ,
},
)
print ( res1 )
# >>> 4
res2 = r . hget ( "bike:1" , "model" )
print ( res2 )
# >>> 'Deimos'
res3 = r . hget ( "bike:1" , "price" )
print ( res3 )
# >>> '4972'
res4 = r . hgetall ( "bike:1" )
print ( res4 )
# >>> {'model': 'Deimos', 'brand': 'Ergonom', 'type': 'Enduro bikes', 'price': '4972'}
res5 = r . hmget ( "bike:1" , [ "model" , "price" ])
print ( res5 )
# >>> ['Deimos', '4972']
res6 = r . hincrby ( "bike:1" , "price" , 100 )
print ( res6 )
# >>> 5072
res7 = r . hincrby ( "bike:1" , "price" , - 100 )
print ( res7 )
# >>> 4972
res11 = r . hincrby ( "bike:1:stats" , "rides" , 1 )
print ( res11 )
# >>> 1
res12 = r . hincrby ( "bike:1:stats" , "rides" , 1 )
print ( res12 )
# >>> 2
res13 = r . hincrby ( "bike:1:stats" , "rides" , 1 )
print ( res13 )
# >>> 3
res14 = r . hincrby ( "bike:1:stats" , "crashes" , 1 )
print ( res14 )
# >>> 1
res15 = r . hincrby ( "bike:1:stats" , "owners" , 1 )
print ( res15 )
# >>> 1
res16 = r . hget ( "bike:1:stats" , "rides" )
print ( res16 )
# >>> 3
res17 = r . hmget ( "bike:1:stats" , [ "crashes" , "owners" ])
print ( res17 )
# >>> ['1', '1']
Copied!
Most Redis hash commands are O(1).
A few commands - such as HKEYS
, HVALS
, and HGETALL
- are O(n), where n is the number of field-value pairs.
Limits
Every hash can store up to 4,294,967,295 (2^32 - 1) field-value pairs.
In practice, your hashes are limited only by the overall memory on the VMs hosting your Redis deployment.
Learn more