Redis 哈希
Redis 哈希简介
Redis 哈希是一种记录类型,其结构为字段值对的集合。您可以使用哈希来表示基本对象以及存储计数器分组等。
Redis 命令行工具
> 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"
已复制!
Python
"""
Code samples for Hash doc pages:
https://redis.github.net.cn/docs/latest/develop/data-types/hashes/
"""
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']
已复制!
Node.js
import assert from 'assert' ;
import { createClient } from 'redis' ;
const client = createClient ();
await client . connect ();
const res1 = await client . hSet (
'bike:1' ,
{
'model' : 'Deimos' ,
'brand' : 'Ergonom' ,
'type' : 'Enduro bikes' ,
'price' : 4972 ,
}
)
console . log ( res1 ) // 4
const res2 = await client . hGet ( 'bike:1' , 'model' )
console . log ( res2 ) // 'Deimos'
const res3 = await client . hGet ( 'bike:1' , 'price' )
console . log ( res3 ) // '4972'
const res4 = await client . hGetAll ( 'bike:1' )
console . log ( res4 )
/*
{
brand: 'Ergonom',
model: 'Deimos',
price: '4972',
type: 'Enduro bikes'
}
*/
const res5 = await client . hmGet ( 'bike:1' , [ 'model' , 'price' ])
console . log ( res5 ) // ['Deimos', '4972']
const res6 = await client . hIncrBy ( 'bike:1' , 'price' , 100 )
console . log ( res6 ) // 5072
const res7 = await client . hIncrBy ( 'bike:1' , 'price' , - 100 )
console . log ( res7 ) // 4972
const res11 = await client . hIncrBy ( 'bike:1:stats' , 'rides' , 1 )
console . log ( res11 ) // 1
const res12 = await client . hIncrBy ( 'bike:1:stats' , 'rides' , 1 )
console . log ( res12 ) // 2
const res13 = await client . hIncrBy ( 'bike:1:stats' , 'rides' , 1 )
console . log ( res13 ) // 3
const res14 = await client . hIncrBy ( 'bike:1:stats' , 'crashes' , 1 )
console . log ( res14 ) // 1
const res15 = await client . hIncrBy ( 'bike:1:stats' , 'owners' , 1 )
console . log ( res15 ) // 1
const res16 = await client . hGet ( 'bike:1:stats' , 'rides' )
console . log ( res16 ) // 3
const res17 = await client . hmGet ( 'bike:1:stats' , [ 'crashes' , 'owners' ])
console . log ( res17 ) // ['1', '1']
已复制!
Java
package io.redis.examples ;
import redis.clients.jedis.UnifiedJedis ;
import java.util.HashMap ;
import java.util.List ;
import java.util.Map ;
public class HashExample {
public void run () {
try ( UnifiedJedis jedis = new UnifiedJedis ( "redis://localhost:6379" )) {
Map < String , String > bike1 = new HashMap <>();
bike1 . put ( "model" , "Deimos" );
bike1 . put ( "brand" , "Ergonom" );
bike1 . put ( "type" , "Enduro bikes" );
bike1 . put ( "price" , "4972" );
Long res1 = jedis . hset ( "bike:1" , bike1 );
System . out . println ( res1 ); // 4
String res2 = jedis . hget ( "bike:1" , "model" );
System . out . println ( res2 ); // Deimos
String res3 = jedis . hget ( "bike:1" , "price" );
System . out . println ( res3 ); // 4972
Map < String , String > res4 = jedis . hgetAll ( "bike:1" );
System . out . println ( res4 ); // {type=Enduro bikes, brand=Ergonom, price=4972, model=Deimos}
List < String > res5 = jedis . hmget ( "bike:1" , "model" , "price" );
System . out . println ( res5 ); // [Deimos, 4972]
Long res6 = jedis . hincrBy ( "bike:1" , "price" , 100 );
System . out . println ( res6 ); // 5072
Long res7 = jedis . hincrBy ( "bike:1" , "price" , - 100 );
System . out . println ( res7 ); // 4972
Long res8 = jedis . hincrBy ( "bike:1:stats" , "rides" , 1 );
System . out . println ( res8 ); // 1
Long res9 = jedis . hincrBy ( "bike:1:stats" , "rides" , 1 );
System . out . println ( res9 ); // 2
Long res10 = jedis . hincrBy ( "bike:1:stats" , "rides" , 1 );
System . out . println ( res10 ); // 3
Long res11 = jedis . hincrBy ( "bike:1:stats" , "crashes" , 1 );
System . out . println ( res11 ); // 1
Long res12 = jedis . hincrBy ( "bike:1:stats" , "owners" , 1 );
System . out . println ( res12 ); // 1
String res13 = jedis . hget ( "bike:1:stats" , "rides" );
System . out . println ( res13 ); // 3
List < String > res14 = jedis . hmget ( "bike:1:stats" , "crashes" , "owners" );
System . out . println ( res14 ); // [1, 1]
}
}
}
已复制!
C#
using NRedisStack.Tests ;
using StackExchange.Redis ;
public class HashExample
{
[SkipIfRedis(Is.OSSCluster)]
public void run ()
{
var muxer = ConnectionMultiplexer . Connect ( "localhost:6379" );
var db = muxer . GetDatabase ();
db . KeyDelete ( "bike:1" );
db . HashSet ( "bike:1" , new HashEntry []
{
new HashEntry ( "model" , "Deimos" ),
new HashEntry ( "brand" , "Ergonom" ),
new HashEntry ( "type" , "Enduro bikes" ),
new HashEntry ( "price" , 4972 )
});
Console . WriteLine ( "Hash Created" );
// Hash Created
var model = db . HashGet ( "bike:1" , "model" );
Console . WriteLine ( $"Model: {model}" );
// Model: Deimos
var price = db . HashGet ( "bike:1" , "price" );
Console . WriteLine ( $"Price: {price}" );
// Price: 4972
var bike = db . HashGetAll ( "bike:1" );
Console . WriteLine ( "bike:1" );
Console . WriteLine ( string . Join ( "\n" , bike . Select ( b => $"{b.Name}: {b.Value}" )));
// Bike:1:
// model: Deimos
// brand: Ergonom
// type: Enduro bikes
// price: 4972
var values = db . HashGet ( "bike:1" , new RedisValue [] { "model" , "price" });
Console . WriteLine ( string . Join ( " " , values ));
// Deimos 4972
var newPrice = db . HashIncrement ( "bike:1" , "price" , 100 );
Console . WriteLine ( $"New price: {newPrice}" );
// New price: 5072
newPrice = db . HashIncrement ( "bike:1" , "price" , - 100 );
Console . WriteLine ( $"New price: {newPrice}" );
// New price: 4972
var rides = db . HashIncrement ( "bike:1" , "rides" );
Console . WriteLine ( $"Rides: {rides}" );
// Rides: 1
rides = db . HashIncrement ( "bike:1" , "rides" );
Console . WriteLine ( $"Rides: {rides}" );
// Rides: 2
rides = db . HashIncrement ( "bike:1" , "rides" );
Console . WriteLine ( $"Rides: {rides}" );
// Rides: 3
var crashes = db . HashIncrement ( "bike:1" , "crashes" );
Console . WriteLine ( $"Crashes: {crashes}" );
// Crashes: 1
var owners = db . HashIncrement ( "bike:1" , "owners" );
Console . WriteLine ( $"Owners: {owners}" );
// Owners: 1
var stats = db . HashGet ( "bike:1" , new RedisValue [] { "crashes" , "owners" });
Console . WriteLine ( $"Bike stats: crashes={stats[0]}, owners={stats[1]}" );
// Bike stats: crashes=1, owners=1
}
}
已复制!
虽然哈希表可以方便地表示对象 ,但实际上,哈希表中可放入的字段数量没有实际限制(可用内存除外),因此,您可以在应用程序内部以多种不同的方式使用哈希表。
该命令HSET 设置哈希的多个字段,而HGET 检索单个字段。HMGET 类似HGET 但返回一个值数组:
Redis 命令行工具
> HMGET bike:1 model price no-such-field
1) "Deimos"
2) "4972"
3) (nil)
已复制!
Python
"""
Code samples for Hash doc pages:
https://redis.github.net.cn/docs/latest/develop/data-types/hashes/
"""
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']
已复制!
Node.js
import assert from 'assert' ;
import { createClient } from 'redis' ;
const client = createClient ();
await client . connect ();
const res1 = await client . hSet (
'bike:1' ,
{
'model' : 'Deimos' ,
'brand' : 'Ergonom' ,
'type' : 'Enduro bikes' ,
'price' : 4972 ,
}
)
console . log ( res1 ) // 4
const res2 = await client . hGet ( 'bike:1' , 'model' )
console . log ( res2 ) // 'Deimos'
const res3 = await client . hGet ( 'bike:1' , 'price' )
console . log ( res3 ) // '4972'
const res4 = await client . hGetAll ( 'bike:1' )
console . log ( res4 )
/*
{
brand: 'Ergonom',
model: 'Deimos',
price: '4972',
type: 'Enduro bikes'
}
*/
const res5 = await client . hmGet ( 'bike:1' , [ 'model' , 'price' ])
console . log ( res5 ) // ['Deimos', '4972']
const res6 = await client . hIncrBy ( 'bike:1' , 'price' , 100 )
console . log ( res6 ) // 5072
const res7 = await client . hIncrBy ( 'bike:1' , 'price' , - 100 )
console . log ( res7 ) // 4972
const res11 = await client . hIncrBy ( 'bike:1:stats' , 'rides' , 1 )
console . log ( res11 ) // 1
const res12 = await client . hIncrBy ( 'bike:1:stats' , 'rides' , 1 )
console . log ( res12 ) // 2
const res13 = await client . hIncrBy ( 'bike:1:stats' , 'rides' , 1 )
console . log ( res13 ) // 3
const res14 = await client . hIncrBy ( 'bike:1:stats' , 'crashes' , 1 )
console . log ( res14 ) // 1
const res15 = await client . hIncrBy ( 'bike:1:stats' , 'owners' , 1 )
console . log ( res15 ) // 1
const res16 = await client . hGet ( 'bike:1:stats' , 'rides' )
console . log ( res16 ) // 3
const res17 = await client . hmGet ( 'bike:1:stats' , [ 'crashes' , 'owners' ])
console . log ( res17 ) // ['1', '1']
已复制!
Java
package io.redis.examples ;
import redis.clients.jedis.UnifiedJedis ;
import java.util.HashMap ;
import java.util.List ;
import java.util.Map ;
public class HashExample {
public void run () {
try ( UnifiedJedis jedis = new UnifiedJedis ( "redis://localhost:6379" )) {
Map < String , String > bike1 = new HashMap <>();
bike1 . put ( "model" , "Deimos" );
bike1 . put ( "brand" , "Ergonom" );
bike1 . put ( "type" , "Enduro bikes" );
bike1 . put ( "price" , "4972" );
Long res1 = jedis . hset ( "bike:1" , bike1 );
System . out . println ( res1 ); // 4
String res2 = jedis . hget ( "bike:1" , "model" );
System . out . println ( res2 ); // Deimos
String res3 = jedis . hget ( "bike:1" , "price" );
System . out . println ( res3 ); // 4972
Map < String , String > res4 = jedis . hgetAll ( "bike:1" );
System . out . println ( res4 ); // {type=Enduro bikes, brand=Ergonom, price=4972, model=Deimos}
List < String > res5 = jedis . hmget ( "bike:1" , "model" , "price" );
System . out . println ( res5 ); // [Deimos, 4972]
Long res6 = jedis . hincrBy ( "bike:1" , "price" , 100 );
System . out . println ( res6 ); // 5072
Long res7 = jedis . hincrBy ( "bike:1" , "price" , - 100 );
System . out . println ( res7 ); // 4972
Long res8 = jedis . hincrBy ( "bike:1:stats" , "rides" , 1 );
System . out . println ( res8 ); // 1
Long res9 = jedis . hincrBy ( "bike:1:stats" , "rides" , 1 );
System . out . println ( res9 ); // 2
Long res10 = jedis . hincrBy ( "bike:1:stats" , "rides" , 1 );
System . out . println ( res10 ); // 3
Long res11 = jedis . hincrBy ( "bike:1:stats" , "crashes" , 1 );
System . out . println ( res11 ); // 1
Long res12 = jedis . hincrBy ( "bike:1:stats" , "owners" , 1 );
System . out . println ( res12 ); // 1
String res13 = jedis . hget ( "bike:1:stats" , "rides" );
System . out . println ( res13 ); // 3
List < String > res14 = jedis . hmget ( "bike:1:stats" , "crashes" , "owners" );
System . out . println ( res14 ); // [1, 1]
}
}
}
已复制!
C#
using NRedisStack.Tests ;
using StackExchange.Redis ;
public class HashExample
{
[SkipIfRedis(Is.OSSCluster)]
public void run ()
{
var muxer = ConnectionMultiplexer . Connect ( "localhost:6379" );
var db = muxer . GetDatabase ();
db . KeyDelete ( "bike:1" );
db . HashSet ( "bike:1" , new HashEntry []
{
new HashEntry ( "model" , "Deimos" ),
new HashEntry ( "brand" , "Ergonom" ),
new HashEntry ( "type" , "Enduro bikes" ),
new HashEntry ( "price" , 4972 )
});
Console . WriteLine ( "Hash Created" );
// Hash Created
var model = db . HashGet ( "bike:1" , "model" );
Console . WriteLine ( $"Model: {model}" );
// Model: Deimos
var price = db . HashGet ( "bike:1" , "price" );
Console . WriteLine ( $"Price: {price}" );
// Price: 4972
var bike = db . HashGetAll ( "bike:1" );
Console . WriteLine ( "bike:1" );
Console . WriteLine ( string . Join ( "\n" , bike . Select ( b => $"{b.Name}: {b.Value}" )));
// Bike:1:
// model: Deimos
// brand: Ergonom
// type: Enduro bikes
// price: 4972
var values = db . HashGet ( "bike:1" , new RedisValue [] { "model" , "price" });
Console . WriteLine ( string . Join ( " " , values ));
// Deimos 4972
var newPrice = db . HashIncrement ( "bike:1" , "price" , 100 );
Console . WriteLine ( $"New price: {newPrice}" );
// New price: 5072
newPrice = db . HashIncrement ( "bike:1" , "price" , - 100 );
Console . WriteLine ( $"New price: {newPrice}" );
// New price: 4972
var rides = db . HashIncrement ( "bike:1" , "rides" );
Console . WriteLine ( $"Rides: {rides}" );
// Rides: 1
rides = db . HashIncrement ( "bike:1" , "rides" );
Console . WriteLine ( $"Rides: {rides}" );
// Rides: 2
rides = db . HashIncrement ( "bike:1" , "rides" );
Console . WriteLine ( $"Rides: {rides}" );
// Rides: 3
var crashes = db . HashIncrement ( "bike:1" , "crashes" );
Console . WriteLine ( $"Crashes: {crashes}" );
// Crashes: 1
var owners = db . HashIncrement ( "bike:1" , "owners" );
Console . WriteLine ( $"Owners: {owners}" );
// Owners: 1
var stats = db . HashGet ( "bike:1" , new RedisValue [] { "crashes" , "owners" });
Console . WriteLine ( $"Bike stats: crashes={stats[0]}, owners={stats[1]}" );
// Bike stats: crashes=1, owners=1
}
}
已复制!
还有一些命令可以对单个字段执行操作,例如HINCRBY :
Redis 命令行工具
> HINCRBY bike:1 price 100
(integer) 5072
> HINCRBY bike:1 price -100
(integer) 4972
已复制!
Python
"""
Code samples for Hash doc pages:
https://redis.github.net.cn/docs/latest/develop/data-types/hashes/
"""
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']
已复制!
Node.js
import assert from 'assert' ;
import { createClient } from 'redis' ;
const client = createClient ();
await client . connect ();
const res1 = await client . hSet (
'bike:1' ,
{
'model' : 'Deimos' ,
'brand' : 'Ergonom' ,
'type' : 'Enduro bikes' ,
'price' : 4972 ,
}
)
console . log ( res1 ) // 4
const res2 = await client . hGet ( 'bike:1' , 'model' )
console . log ( res2 ) // 'Deimos'
const res3 = await client . hGet ( 'bike:1' , 'price' )
console . log ( res3 ) // '4972'
const res4 = await client . hGetAll ( 'bike:1' )
console . log ( res4 )
/*
{
brand: 'Ergonom',
model: 'Deimos',
price: '4972',
type: 'Enduro bikes'
}
*/
const res5 = await client . hmGet ( 'bike:1' , [ 'model' , 'price' ])
console . log ( res5 ) // ['Deimos', '4972']
const res6 = await client . hIncrBy ( 'bike:1' , 'price' , 100 )
console . log ( res6 ) // 5072
const res7 = await client . hIncrBy ( 'bike:1' , 'price' , - 100 )
console . log ( res7 ) // 4972
const res11 = await client . hIncrBy ( 'bike:1:stats' , 'rides' , 1 )
console . log ( res11 ) // 1
const res12 = await client . hIncrBy ( 'bike:1:stats' , 'rides' , 1 )
console . log ( res12 ) // 2
const res13 = await client . hIncrBy ( 'bike:1:stats' , 'rides' , 1 )
console . log ( res13 ) // 3
const res14 = await client . hIncrBy ( 'bike:1:stats' , 'crashes' , 1 )
console . log ( res14 ) // 1
const res15 = await client . hIncrBy ( 'bike:1:stats' , 'owners' , 1 )
console . log ( res15 ) // 1
const res16 = await client . hGet ( 'bike:1:stats' , 'rides' )
console . log ( res16 ) // 3
const res17 = await client . hmGet ( 'bike:1:stats' , [ 'crashes' , 'owners' ])
console . log ( res17 ) // ['1', '1']
已复制!
Java
package io.redis.examples ;
import redis.clients.jedis.UnifiedJedis ;
import java.util.HashMap ;
import java.util.List ;
import java.util.Map ;
public class HashExample {
public void run () {
try ( UnifiedJedis jedis = new UnifiedJedis ( "redis://localhost:6379" )) {
Map < String , String > bike1 = new HashMap <>();
bike1 . put ( "model" , "Deimos" );
bike1 . put ( "brand" , "Ergonom" );
bike1 . put ( "type" , "Enduro bikes" );
bike1 . put ( "price" , "4972" );
Long res1 = jedis . hset ( "bike:1" , bike1 );
System . out . println ( res1 ); // 4
String res2 = jedis . hget ( "bike:1" , "model" );
System . out . println ( res2 ); // Deimos
String res3 = jedis . hget ( "bike:1" , "price" );
System . out . println ( res3 ); // 4972
Map < String , String > res4 = jedis . hgetAll ( "bike:1" );
System . out . println ( res4 ); // {type=Enduro bikes, brand=Ergonom, price=4972, model=Deimos}
List < String > res5 = jedis . hmget ( "bike:1" , "model" , "price" );
System . out . println ( res5 ); // [Deimos, 4972]
Long res6 = jedis . hincrBy ( "bike:1" , "price" , 100 );
System . out . println ( res6 ); // 5072
Long res7 = jedis . hincrBy ( "bike:1" , "price" , - 100 );
System . out . println ( res7 ); // 4972
Long res8 = jedis . hincrBy ( "bike:1:stats" , "rides" , 1 );
System . out . println ( res8 ); // 1
Long res9 = jedis . hincrBy ( "bike:1:stats" , "rides" , 1 );
System . out . println ( res9 ); // 2
Long res10 = jedis . hincrBy ( "bike:1:stats" , "rides" , 1 );
System . out . println ( res10 ); // 3
Long res11 = jedis . hincrBy ( "bike:1:stats" , "crashes" , 1 );
System . out . println ( res11 ); // 1
Long res12 = jedis . hincrBy ( "bike:1:stats" , "owners" , 1 );
System . out . println ( res12 ); // 1
String res13 = jedis . hget ( "bike:1:stats" , "rides" );
System . out . println ( res13 ); // 3
List < String > res14 = jedis . hmget ( "bike:1:stats" , "crashes" , "owners" );
System . out . println ( res14 ); // [1, 1]
}
}
}
已复制!
C#
using NRedisStack.Tests ;
using StackExchange.Redis ;
public class HashExample
{
[SkipIfRedis(Is.OSSCluster)]
public void run ()
{
var muxer = ConnectionMultiplexer . Connect ( "localhost:6379" );
var db = muxer . GetDatabase ();
db . KeyDelete ( "bike:1" );
db . HashSet ( "bike:1" , new HashEntry []
{
new HashEntry ( "model" , "Deimos" ),
new HashEntry ( "brand" , "Ergonom" ),
new HashEntry ( "type" , "Enduro bikes" ),
new HashEntry ( "price" , 4972 )
});
Console . WriteLine ( "Hash Created" );
// Hash Created
var model = db . HashGet ( "bike:1" , "model" );
Console . WriteLine ( $"Model: {model}" );
// Model: Deimos
var price = db . HashGet ( "bike:1" , "price" );
Console . WriteLine ( $"Price: {price}" );
// Price: 4972
var bike = db . HashGetAll ( "bike:1" );
Console . WriteLine ( "bike:1" );
Console . WriteLine ( string . Join ( "\n" , bike . Select ( b => $"{b.Name}: {b.Value}" )));
// Bike:1:
// model: Deimos
// brand: Ergonom
// type: Enduro bikes
// price: 4972
var values = db . HashGet ( "bike:1" , new RedisValue [] { "model" , "price" });
Console . WriteLine ( string . Join ( " " , values ));
// Deimos 4972
var newPrice = db . HashIncrement ( "bike:1" , "price" , 100 );
Console . WriteLine ( $"New price: {newPrice}" );
// New price: 5072
newPrice = db . HashIncrement ( "bike:1" , "price" , - 100 );
Console . WriteLine ( $"New price: {newPrice}" );
// New price: 4972
var rides = db . HashIncrement ( "bike:1" , "rides" );
Console . WriteLine ( $"Rides: {rides}" );
// Rides: 1
rides = db . HashIncrement ( "bike:1" , "rides" );
Console . WriteLine ( $"Rides: {rides}" );
// Rides: 2
rides = db . HashIncrement ( "bike:1" , "rides" );
Console . WriteLine ( $"Rides: {rides}" );
// Rides: 3
var crashes = db . HashIncrement ( "bike:1" , "crashes" );
Console . WriteLine ( $"Crashes: {crashes}" );
// Crashes: 1
var owners = db . HashIncrement ( "bike:1" , "owners" );
Console . WriteLine ( $"Owners: {owners}" );
// Owners: 1
var stats = db . HashGet ( "bike:1" , new RedisValue [] { "crashes" , "owners" });
Console . WriteLine ( $"Bike stats: crashes={stats[0]}, owners={stats[1]}" );
// Bike stats: crashes=1, owners=1
}
}
已复制!
您可以在文档中找到哈希命令的完整列表 。
值得注意的是,小哈希值(即少数具有小值的元素)以特殊方式在内存中编码,这使得它们的内存效率非常高。
基本命令
查看哈希命令的完整列表 。
示例
存储自行车:1 被骑行、撞车或更换主人的次数的计数器:
Redis 命令行工具
> 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"
已复制!
Python
"""
Code samples for Hash doc pages:
https://redis.github.net.cn/docs/latest/develop/data-types/hashes/
"""
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']
已复制!
Node.js
import assert from 'assert' ;
import { createClient } from 'redis' ;
const client = createClient ();
await client . connect ();
const res1 = await client . hSet (
'bike:1' ,
{
'model' : 'Deimos' ,
'brand' : 'Ergonom' ,
'type' : 'Enduro bikes' ,
'price' : 4972 ,
}
)
console . log ( res1 ) // 4
const res2 = await client . hGet ( 'bike:1' , 'model' )
console . log ( res2 ) // 'Deimos'
const res3 = await client . hGet ( 'bike:1' , 'price' )
console . log ( res3 ) // '4972'
const res4 = await client . hGetAll ( 'bike:1' )
console . log ( res4 )
/*
{
brand: 'Ergonom',
model: 'Deimos',
price: '4972',
type: 'Enduro bikes'
}
*/
const res5 = await client . hmGet ( 'bike:1' , [ 'model' , 'price' ])
console . log ( res5 ) // ['Deimos', '4972']
const res6 = await client . hIncrBy ( 'bike:1' , 'price' , 100 )
console . log ( res6 ) // 5072
const res7 = await client . hIncrBy ( 'bike:1' , 'price' , - 100 )
console . log ( res7 ) // 4972
const res11 = await client . hIncrBy ( 'bike:1:stats' , 'rides' , 1 )
console . log ( res11 ) // 1
const res12 = await client . hIncrBy ( 'bike:1:stats' , 'rides' , 1 )
console . log ( res12 ) // 2
const res13 = await client . hIncrBy ( 'bike:1:stats' , 'rides' , 1 )
console . log ( res13 ) // 3
const res14 = await client . hIncrBy ( 'bike:1:stats' , 'crashes' , 1 )
console . log ( res14 ) // 1
const res15 = await client . hIncrBy ( 'bike:1:stats' , 'owners' , 1 )
console . log ( res15 ) // 1
const res16 = await client . hGet ( 'bike:1:stats' , 'rides' )
console . log ( res16 ) // 3
const res17 = await client . hmGet ( 'bike:1:stats' , [ 'crashes' , 'owners' ])
console . log ( res17 ) // ['1', '1']
已复制!
Java
package io.redis.examples ;
import redis.clients.jedis.UnifiedJedis ;
import java.util.HashMap ;
import java.util.List ;
import java.util.Map ;
public class HashExample {
public void run () {
try ( UnifiedJedis jedis = new UnifiedJedis ( "redis://localhost:6379" )) {
Map < String , String > bike1 = new HashMap <>();
bike1 . put ( "model" , "Deimos" );
bike1 . put ( "brand" , "Ergonom" );
bike1 . put ( "type" , "Enduro bikes" );
bike1 . put ( "price" , "4972" );
Long res1 = jedis . hset ( "bike:1" , bike1 );
System . out . println ( res1 ); // 4
String res2 = jedis . hget ( "bike:1" , "model" );
System . out . println ( res2 ); // Deimos
String res3 = jedis . hget ( "bike:1" , "price" );
System . out . println ( res3 ); // 4972
Map < String , String > res4 = jedis . hgetAll ( "bike:1" );
System . out . println ( res4 ); // {type=Enduro bikes, brand=Ergonom, price=4972, model=Deimos}
List < String > res5 = jedis . hmget ( "bike:1" , "model" , "price" );
System . out . println ( res5 ); // [Deimos, 4972]
Long res6 = jedis . hincrBy ( "bike:1" , "price" , 100 );
System . out . println ( res6 ); // 5072
Long res7 = jedis . hincrBy ( "bike:1" , "price" , - 100 );
System . out . println ( res7 ); // 4972
Long res8 = jedis . hincrBy ( "bike:1:stats" , "rides" , 1 );
System . out . println ( res8 ); // 1
Long res9 = jedis . hincrBy ( "bike:1:stats" , "rides" , 1 );
System . out . println ( res9 ); // 2
Long res10 = jedis . hincrBy ( "bike:1:stats" , "rides" , 1 );
System . out . println ( res10 ); // 3
Long res11 = jedis . hincrBy ( "bike:1:stats" , "crashes" , 1 );
System . out . println ( res11 ); // 1
Long res12 = jedis . hincrBy ( "bike:1:stats" , "owners" , 1 );
System . out . println ( res12 ); // 1
String res13 = jedis . hget ( "bike:1:stats" , "rides" );
System . out . println ( res13 ); // 3
List < String > res14 = jedis . hmget ( "bike:1:stats" , "crashes" , "owners" );
System . out . println ( res14 ); // [1, 1]
}
}
}
已复制!
C#
using NRedisStack.Tests ;
using StackExchange.Redis ;
public class HashExample
{
[SkipIfRedis(Is.OSSCluster)]
public void run ()
{
var muxer = ConnectionMultiplexer . Connect ( "localhost:6379" );
var db = muxer . GetDatabase ();
db . KeyDelete ( "bike:1" );
db . HashSet ( "bike:1" , new HashEntry []
{
new HashEntry ( "model" , "Deimos" ),
new HashEntry ( "brand" , "Ergonom" ),
new HashEntry ( "type" , "Enduro bikes" ),
new HashEntry ( "price" , 4972 )
});
Console . WriteLine ( "Hash Created" );
// Hash Created
var model = db . HashGet ( "bike:1" , "model" );
Console . WriteLine ( $"Model: {model}" );
// Model: Deimos
var price = db . HashGet ( "bike:1" , "price" );
Console . WriteLine ( $"Price: {price}" );
// Price: 4972
var bike = db . HashGetAll ( "bike:1" );
Console . WriteLine ( "bike:1" );
Console . WriteLine ( string . Join ( "\n" , bike . Select ( b => $"{b.Name}: {b.Value}" )));
// Bike:1:
// model: Deimos
// brand: Ergonom
// type: Enduro bikes
// price: 4972
var values = db . HashGet ( "bike:1" , new RedisValue [] { "model" , "price" });
Console . WriteLine ( string . Join ( " " , values ));
// Deimos 4972
var newPrice = db . HashIncrement ( "bike:1" , "price" , 100 );
Console . WriteLine ( $"New price: {newPrice}" );
// New price: 5072
newPrice = db . HashIncrement ( "bike:1" , "price" , - 100 );
Console . WriteLine ( $"New price: {newPrice}" );
// New price: 4972
var rides = db . HashIncrement ( "bike:1" , "rides" );
Console . WriteLine ( $"Rides: {rides}" );
// Rides: 1
rides = db . HashIncrement ( "bike:1" , "rides" );
Console . WriteLine ( $"Rides: {rides}" );
// Rides: 2
rides = db . HashIncrement ( "bike:1" , "rides" );
Console . WriteLine ( $"Rides: {rides}" );
// Rides: 3
var crashes = db . HashIncrement ( "bike:1" , "crashes" );
Console . WriteLine ( $"Crashes: {crashes}" );
// Crashes: 1
var owners = db . HashIncrement ( "bike:1" , "owners" );
Console . WriteLine ( $"Owners: {owners}" );
// Owners: 1
var stats = db . HashGet ( "bike:1" , new RedisValue [] { "crashes" , "owners" });
Console . WriteLine ( $"Bike stats: crashes={stats[0]}, owners={stats[1]}" );
// Bike stats: crashes=1, owners=1
}
}
已复制!
字段过期
Redis Community Edition 7.4 中的新功能是能够为各个哈希字段指定过期时间或生存时间 (TTL) 值。此功能与密钥过期功能 类似,并且包含许多类似的命令。
使用以下命令为特定字段设置确切的到期时间或 TTL 值:
使用以下命令检索特定字段过期的确切时间或剩余 TTL:
使用以下命令删除特定字段的过期时间:
常见字段过期用例
事件跟踪 :使用哈希键存储过去一小时的事件。将每个事件的 TTL 设置为一小时。用于HLEN统计过去一小时的事件。
欺诈检测 :创建一个包含事件每小时计数器的哈希。将每个字段的 TTL 设置为 48 小时。查询哈希以获取过去 48 小时内每小时的事件数。
客户会话管理 :将客户数据存储在哈希键中。为每个会话创建一个新的哈希键,并将会话字段添加到客户的哈希键中。会话过期时,会话键和客户哈希键中的会话字段都会自动过期。
活动会话跟踪 :将所有活动会话存储在哈希键中。将每个会话的 TTL 设置为在不活动后自动过期。用于HLEN计算活动会话。
字段过期示例
官方客户端库尚不支持哈希字段过期,但您现在可以使用Python(redis-py) 和Java(Jedis) 客户端库的测试版本来测试哈希字段过期。
以下是一些 Python 示例,演示如何使用字段过期。
考虑一个用于存储传感器数据的哈希数据集,其结构如下:
event = {
'air_quality' : 256 ,
'Battery_level' : 89
}
client . hset ( 'sensor:sensor1' , mapping = event )
设置并检索哈希中多个字段的 TTL:
# set the TTL for two hash fields to 60 seconds
client . hexpire ( 'sensor:sensor1' , 60 , 'air_quality' , 'battery_level' )
ttl = client . httl ( 'sensor:sensor1' , 'air_quality' , 'battery_level' )
print ( ttl )
# prints [60]
以毫秒为单位设置和检索哈希字段的 TTL:
# set the TTL of the 'air_quality' field in milliseconds
client . hpexpire ( 'sensor:sensor1' , 60000 , 'air_quality' )
# and retrieve it
pttl = client . hpttl ( 'sensor:sensor1' , 'air_quality' )
print ( pttl )
# prints [60000]
设置并检索哈希字段的过期时间戳:
# set the expiration of 'air_quality' to now + 24 hours
# (similar to setting the TTL to 24 hours)
client . hexpireat ( 'sensor:sensor1' ,
datetime . now () + timedelta ( hours = 24 ),
'air_quality' )
# and retrieve it
expire_time = client . hexpiretime ( 'sensor:sensor1' , 'air_quality' )
print ( expire_time )
# prints [1717668041]
大多数 Redis 哈希命令都是 O(1)。
一些命令(例如HKEYS 、、HVALS )HGETALL 以及大多数与到期相关的命令都是 O(n),其中n 是字段值对的数量。
限制
每个哈希最多可以存储 4,294,967,295 (2^32 - 1) 个字段值对。实际上,您的哈希仅受托管 Redis 部署的虚拟机上的总内存限制。
了解更多