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"
"""
Code samples for Hash doc pages:
https://redis.ac.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']
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']
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]
}
}
}
package io.redis.examples.async;
import io.lettuce.core.*;
import io.lettuce.core.api.async.RedisAsyncCommands;
import io.lettuce.core.api.StatefulRedisConnection;
import java.util.*;
import java.util.concurrent.CompletableFuture;
public class HashExample {
public void run() {
RedisClient redisClient = RedisClient.create("redis://localhost:6379");
try (StatefulRedisConnection<String, String> connection = redisClient.connect()) {
RedisAsyncCommands<String, String> asyncCommands = connection.async();
Map<String, String> bike1 = new HashMap<>();
bike1.put("model", "Deimos");
bike1.put("brand", "Ergonom");
bike1.put("type", "Enduro bikes");
bike1.put("price", "4972");
CompletableFuture<Void> setGetAll = asyncCommands.hset("bike:1", bike1).thenCompose(res1 -> {
System.out.println(res1); // >>> 4
return asyncCommands.hget("bike:1", "model");
}).thenCompose(res2 -> {
System.out.println(res2); // >>> Deimos
return asyncCommands.hget("bike:1", "price");
}).thenCompose(res3 -> {
System.out.println(res3); // >>> 4972
return asyncCommands.hgetall("bike:1");
})
.thenAccept(System.out::println)
// >>> {type=Enduro bikes, brand=Ergonom, price=4972, model=Deimos}
.toCompletableFuture();
CompletableFuture<Void> hmGet = setGetAll.thenCompose(res4 -> {
return asyncCommands.hmget("bike:1", "model", "price");
})
.thenAccept(System.out::println)
// [KeyValue[model, Deimos], KeyValue[price, 4972]]
.toCompletableFuture();
CompletableFuture<Void> hIncrBy = hmGet.thenCompose(r -> {
return asyncCommands.hincrby("bike:1", "price", 100);
}).thenCompose(res6 -> {
System.out.println(res6); // >>> 5072
return asyncCommands.hincrby("bike:1", "price", -100);
})
.thenAccept(System.out::println)
// >>> 4972
.toCompletableFuture();
CompletableFuture<Void> incrByGetMget = asyncCommands.hincrby("bike:1:stats", "rides", 1).thenCompose(res7 -> {
System.out.println(res7); // >>> 1
return asyncCommands.hincrby("bike:1:stats", "rides", 1);
}).thenCompose(res8 -> {
System.out.println(res8); // >>> 2
return asyncCommands.hincrby("bike:1:stats", "rides", 1);
}).thenCompose(res9 -> {
System.out.println(res9); // >>> 3
return asyncCommands.hincrby("bike:1:stats", "crashes", 1);
}).thenCompose(res10 -> {
System.out.println(res10); // >>> 1
return asyncCommands.hincrby("bike:1:stats", "owners", 1);
}).thenCompose(res11 -> {
System.out.println(res11); // >>> 1
return asyncCommands.hget("bike:1:stats", "rides");
}).thenCompose(res12 -> {
System.out.println(res12); // >>> 3
return asyncCommands.hmget("bike:1:stats", "crashes", "owners");
})
.thenAccept(System.out::println)
// >>> [KeyValue[crashes, 1], KeyValue[owners, 1]]
.toCompletableFuture();
CompletableFuture.allOf(
hIncrBy, incrByGetMget).join();
} finally {
redisClient.shutdown();
}
}
}
package example_commands_test
import (
"context"
"fmt"
"github.com/redis/go-redis/v9"
)
func ExampleClient_set_get_all() {
ctx := context.Background()
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password docs
DB: 0, // use default DB
})
hashFields := []string{
"model", "Deimos",
"brand", "Ergonom",
"type", "Enduro bikes",
"price", "4972",
}
res1, err := rdb.HSet(ctx, "bike:1", hashFields).Result()
if err != nil {
panic(err)
}
fmt.Println(res1) // >>> 4
res2, err := rdb.HGet(ctx, "bike:1", "model").Result()
if err != nil {
panic(err)
}
fmt.Println(res2) // >>> Deimos
res3, err := rdb.HGet(ctx, "bike:1", "price").Result()
if err != nil {
panic(err)
}
fmt.Println(res3) // >>> 4972
cmdReturn := rdb.HGetAll(ctx, "bike:1")
res4, err := cmdReturn.Result()
if err != nil {
panic(err)
}
fmt.Println(res4)
// >>> map[brand:Ergonom model:Deimos price:4972 type:Enduro bikes]
type BikeInfo struct {
Model string `redis:"model"`
Brand string `redis:"brand"`
Type string `redis:"type"`
Price int `redis:"price"`
}
var res4a BikeInfo
if err := cmdReturn.Scan(&res4a); err != nil {
panic(err)
}
fmt.Printf("Model: %v, Brand: %v, Type: %v, Price: $%v\n",
res4a.Model, res4a.Brand, res4a.Type, res4a.Price)
// >>> Model: Deimos, Brand: Ergonom, Type: Enduro bikes, Price: $4972
}
func ExampleClient_hmget() {
ctx := context.Background()
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password docs
DB: 0, // use default DB
})
hashFields := []string{
"model", "Deimos",
"brand", "Ergonom",
"type", "Enduro bikes",
"price", "4972",
}
_, err := rdb.HSet(ctx, "bike:1", hashFields).Result()
if err != nil {
panic(err)
}
cmdReturn := rdb.HMGet(ctx, "bike:1", "model", "price")
res5, err := cmdReturn.Result()
if err != nil {
panic(err)
}
fmt.Println(res5) // >>> [Deimos 4972]
type BikeInfo struct {
Model string `redis:"model"`
Brand string `redis:"-"`
Type string `redis:"-"`
Price int `redis:"price"`
}
var res5a BikeInfo
if err := cmdReturn.Scan(&res5a); err != nil {
panic(err)
}
fmt.Printf("Model: %v, Price: $%v\n", res5a.Model, res5a.Price)
// >>> Model: Deimos, Price: $4972
}
func ExampleClient_hincrby() {
ctx := context.Background()
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password docs
DB: 0, // use default DB
})
hashFields := []string{
"model", "Deimos",
"brand", "Ergonom",
"type", "Enduro bikes",
"price", "4972",
}
_, err := rdb.HSet(ctx, "bike:1", hashFields).Result()
if err != nil {
panic(err)
}
res6, err := rdb.HIncrBy(ctx, "bike:1", "price", 100).Result()
if err != nil {
panic(err)
}
fmt.Println(res6) // >>> 5072
res7, err := rdb.HIncrBy(ctx, "bike:1", "price", -100).Result()
if err != nil {
panic(err)
}
fmt.Println(res7) // >>> 4972
}
func ExampleClient_incrby_get_mget() {
ctx := context.Background()
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password docs
DB: 0, // use default DB
})
res8, err := rdb.HIncrBy(ctx, "bike:1:stats", "rides", 1).Result()
if err != nil {
panic(err)
}
fmt.Println(res8) // >>> 1
res9, err := rdb.HIncrBy(ctx, "bike:1:stats", "rides", 1).Result()
if err != nil {
panic(err)
}
fmt.Println(res9) // >>> 2
res10, err := rdb.HIncrBy(ctx, "bike:1:stats", "rides", 1).Result()
if err != nil {
panic(err)
}
fmt.Println(res10) // >>> 3
res11, err := rdb.HIncrBy(ctx, "bike:1:stats", "crashes", 1).Result()
if err != nil {
panic(err)
}
fmt.Println(res11) // >>> 1
res12, err := rdb.HIncrBy(ctx, "bike:1:stats", "owners", 1).Result()
if err != nil {
panic(err)
}
fmt.Println(res12) // >>> 1
res13, err := rdb.HGet(ctx, "bike:1:stats", "rides").Result()
if err != nil {
panic(err)
}
fmt.Println(res13) // >>> 3
res14, err := rdb.HMGet(ctx, "bike:1:stats", "crashes", "owners").Result()
if err != nil {
panic(err)
}
fmt.Println(res14) // >>> [1 1]
}
using NRedisStack.Tests;
using StackExchange.Redis;
public class HashExample
{
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
但返回一个值数组
> HMGET bike:1 model price no-such-field
1) "Deimos"
2) "4972"
3) (nil)
"""
Code samples for Hash doc pages:
https://redis.ac.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']
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']
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]
}
}
}
package io.redis.examples.async;
import io.lettuce.core.*;
import io.lettuce.core.api.async.RedisAsyncCommands;
import io.lettuce.core.api.StatefulRedisConnection;
import java.util.*;
import java.util.concurrent.CompletableFuture;
public class HashExample {
public void run() {
RedisClient redisClient = RedisClient.create("redis://localhost:6379");
try (StatefulRedisConnection<String, String> connection = redisClient.connect()) {
RedisAsyncCommands<String, String> asyncCommands = connection.async();
Map<String, String> bike1 = new HashMap<>();
bike1.put("model", "Deimos");
bike1.put("brand", "Ergonom");
bike1.put("type", "Enduro bikes");
bike1.put("price", "4972");
CompletableFuture<Void> setGetAll = asyncCommands.hset("bike:1", bike1).thenCompose(res1 -> {
System.out.println(res1); // >>> 4
return asyncCommands.hget("bike:1", "model");
}).thenCompose(res2 -> {
System.out.println(res2); // >>> Deimos
return asyncCommands.hget("bike:1", "price");
}).thenCompose(res3 -> {
System.out.println(res3); // >>> 4972
return asyncCommands.hgetall("bike:1");
})
.thenAccept(System.out::println)
// >>> {type=Enduro bikes, brand=Ergonom, price=4972, model=Deimos}
.toCompletableFuture();
CompletableFuture<Void> hmGet = setGetAll.thenCompose(res4 -> {
return asyncCommands.hmget("bike:1", "model", "price");
})
.thenAccept(System.out::println)
// [KeyValue[model, Deimos], KeyValue[price, 4972]]
.toCompletableFuture();
CompletableFuture<Void> hIncrBy = hmGet.thenCompose(r -> {
return asyncCommands.hincrby("bike:1", "price", 100);
}).thenCompose(res6 -> {
System.out.println(res6); // >>> 5072
return asyncCommands.hincrby("bike:1", "price", -100);
})
.thenAccept(System.out::println)
// >>> 4972
.toCompletableFuture();
CompletableFuture<Void> incrByGetMget = asyncCommands.hincrby("bike:1:stats", "rides", 1).thenCompose(res7 -> {
System.out.println(res7); // >>> 1
return asyncCommands.hincrby("bike:1:stats", "rides", 1);
}).thenCompose(res8 -> {
System.out.println(res8); // >>> 2
return asyncCommands.hincrby("bike:1:stats", "rides", 1);
}).thenCompose(res9 -> {
System.out.println(res9); // >>> 3
return asyncCommands.hincrby("bike:1:stats", "crashes", 1);
}).thenCompose(res10 -> {
System.out.println(res10); // >>> 1
return asyncCommands.hincrby("bike:1:stats", "owners", 1);
}).thenCompose(res11 -> {
System.out.println(res11); // >>> 1
return asyncCommands.hget("bike:1:stats", "rides");
}).thenCompose(res12 -> {
System.out.println(res12); // >>> 3
return asyncCommands.hmget("bike:1:stats", "crashes", "owners");
})
.thenAccept(System.out::println)
// >>> [KeyValue[crashes, 1], KeyValue[owners, 1]]
.toCompletableFuture();
CompletableFuture.allOf(
hIncrBy, incrByGetMget).join();
} finally {
redisClient.shutdown();
}
}
}
package example_commands_test
import (
"context"
"fmt"
"github.com/redis/go-redis/v9"
)
func ExampleClient_set_get_all() {
ctx := context.Background()
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password docs
DB: 0, // use default DB
})
hashFields := []string{
"model", "Deimos",
"brand", "Ergonom",
"type", "Enduro bikes",
"price", "4972",
}
res1, err := rdb.HSet(ctx, "bike:1", hashFields).Result()
if err != nil {
panic(err)
}
fmt.Println(res1) // >>> 4
res2, err := rdb.HGet(ctx, "bike:1", "model").Result()
if err != nil {
panic(err)
}
fmt.Println(res2) // >>> Deimos
res3, err := rdb.HGet(ctx, "bike:1", "price").Result()
if err != nil {
panic(err)
}
fmt.Println(res3) // >>> 4972
cmdReturn := rdb.HGetAll(ctx, "bike:1")
res4, err := cmdReturn.Result()
if err != nil {
panic(err)
}
fmt.Println(res4)
// >>> map[brand:Ergonom model:Deimos price:4972 type:Enduro bikes]
type BikeInfo struct {
Model string `redis:"model"`
Brand string `redis:"brand"`
Type string `redis:"type"`
Price int `redis:"price"`
}
var res4a BikeInfo
if err := cmdReturn.Scan(&res4a); err != nil {
panic(err)
}
fmt.Printf("Model: %v, Brand: %v, Type: %v, Price: $%v\n",
res4a.Model, res4a.Brand, res4a.Type, res4a.Price)
// >>> Model: Deimos, Brand: Ergonom, Type: Enduro bikes, Price: $4972
}
func ExampleClient_hmget() {
ctx := context.Background()
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password docs
DB: 0, // use default DB
})
hashFields := []string{
"model", "Deimos",
"brand", "Ergonom",
"type", "Enduro bikes",
"price", "4972",
}
_, err := rdb.HSet(ctx, "bike:1", hashFields).Result()
if err != nil {
panic(err)
}
cmdReturn := rdb.HMGet(ctx, "bike:1", "model", "price")
res5, err := cmdReturn.Result()
if err != nil {
panic(err)
}
fmt.Println(res5) // >>> [Deimos 4972]
type BikeInfo struct {
Model string `redis:"model"`
Brand string `redis:"-"`
Type string `redis:"-"`
Price int `redis:"price"`
}
var res5a BikeInfo
if err := cmdReturn.Scan(&res5a); err != nil {
panic(err)
}
fmt.Printf("Model: %v, Price: $%v\n", res5a.Model, res5a.Price)
// >>> Model: Deimos, Price: $4972
}
func ExampleClient_hincrby() {
ctx := context.Background()
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password docs
DB: 0, // use default DB
})
hashFields := []string{
"model", "Deimos",
"brand", "Ergonom",
"type", "Enduro bikes",
"price", "4972",
}
_, err := rdb.HSet(ctx, "bike:1", hashFields).Result()
if err != nil {
panic(err)
}
res6, err := rdb.HIncrBy(ctx, "bike:1", "price", 100).Result()
if err != nil {
panic(err)
}
fmt.Println(res6) // >>> 5072
res7, err := rdb.HIncrBy(ctx, "bike:1", "price", -100).Result()
if err != nil {
panic(err)
}
fmt.Println(res7) // >>> 4972
}
func ExampleClient_incrby_get_mget() {
ctx := context.Background()
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password docs
DB: 0, // use default DB
})
res8, err := rdb.HIncrBy(ctx, "bike:1:stats", "rides", 1).Result()
if err != nil {
panic(err)
}
fmt.Println(res8) // >>> 1
res9, err := rdb.HIncrBy(ctx, "bike:1:stats", "rides", 1).Result()
if err != nil {
panic(err)
}
fmt.Println(res9) // >>> 2
res10, err := rdb.HIncrBy(ctx, "bike:1:stats", "rides", 1).Result()
if err != nil {
panic(err)
}
fmt.Println(res10) // >>> 3
res11, err := rdb.HIncrBy(ctx, "bike:1:stats", "crashes", 1).Result()
if err != nil {
panic(err)
}
fmt.Println(res11) // >>> 1
res12, err := rdb.HIncrBy(ctx, "bike:1:stats", "owners", 1).Result()
if err != nil {
panic(err)
}
fmt.Println(res12) // >>> 1
res13, err := rdb.HGet(ctx, "bike:1:stats", "rides").Result()
if err != nil {
panic(err)
}
fmt.Println(res13) // >>> 3
res14, err := rdb.HMGet(ctx, "bike:1:stats", "crashes", "owners").Result()
if err != nil {
panic(err)
}
fmt.Println(res14) // >>> [1 1]
}
using NRedisStack.Tests;
using StackExchange.Redis;
public class HashExample
{
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
> HINCRBY bike:1 price 100
(integer) 5072
> HINCRBY bike:1 price -100
(integer) 4972
"""
Code samples for Hash doc pages:
https://redis.ac.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']
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']
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]
}
}
}
package io.redis.examples.async;
import io.lettuce.core.*;
import io.lettuce.core.api.async.RedisAsyncCommands;
import io.lettuce.core.api.StatefulRedisConnection;
import java.util.*;
import java.util.concurrent.CompletableFuture;
public class HashExample {
public void run() {
RedisClient redisClient = RedisClient.create("redis://localhost:6379");
try (StatefulRedisConnection<String, String> connection = redisClient.connect()) {
RedisAsyncCommands<String, String> asyncCommands = connection.async();
Map<String, String> bike1 = new HashMap<>();
bike1.put("model", "Deimos");
bike1.put("brand", "Ergonom");
bike1.put("type", "Enduro bikes");
bike1.put("price", "4972");
CompletableFuture<Void> setGetAll = asyncCommands.hset("bike:1", bike1).thenCompose(res1 -> {
System.out.println(res1); // >>> 4
return asyncCommands.hget("bike:1", "model");
}).thenCompose(res2 -> {
System.out.println(res2); // >>> Deimos
return asyncCommands.hget("bike:1", "price");
}).thenCompose(res3 -> {
System.out.println(res3); // >>> 4972
return asyncCommands.hgetall("bike:1");
})
.thenAccept(System.out::println)
// >>> {type=Enduro bikes, brand=Ergonom, price=4972, model=Deimos}
.toCompletableFuture();
CompletableFuture<Void> hmGet = setGetAll.thenCompose(res4 -> {
return asyncCommands.hmget("bike:1", "model", "price");
})
.thenAccept(System.out::println)
// [KeyValue[model, Deimos], KeyValue[price, 4972]]
.toCompletableFuture();
CompletableFuture<Void> hIncrBy = hmGet.thenCompose(r -> {
return asyncCommands.hincrby("bike:1", "price", 100);
}).thenCompose(res6 -> {
System.out.println(res6); // >>> 5072
return asyncCommands.hincrby("bike:1", "price", -100);
})
.thenAccept(System.out::println)
// >>> 4972
.toCompletableFuture();
CompletableFuture<Void> incrByGetMget = asyncCommands.hincrby("bike:1:stats", "rides", 1).thenCompose(res7 -> {
System.out.println(res7); // >>> 1
return asyncCommands.hincrby("bike:1:stats", "rides", 1);
}).thenCompose(res8 -> {
System.out.println(res8); // >>> 2
return asyncCommands.hincrby("bike:1:stats", "rides", 1);
}).thenCompose(res9 -> {
System.out.println(res9); // >>> 3
return asyncCommands.hincrby("bike:1:stats", "crashes", 1);
}).thenCompose(res10 -> {
System.out.println(res10); // >>> 1
return asyncCommands.hincrby("bike:1:stats", "owners", 1);
}).thenCompose(res11 -> {
System.out.println(res11); // >>> 1
return asyncCommands.hget("bike:1:stats", "rides");
}).thenCompose(res12 -> {
System.out.println(res12); // >>> 3
return asyncCommands.hmget("bike:1:stats", "crashes", "owners");
})
.thenAccept(System.out::println)
// >>> [KeyValue[crashes, 1], KeyValue[owners, 1]]
.toCompletableFuture();
CompletableFuture.allOf(
hIncrBy, incrByGetMget).join();
} finally {
redisClient.shutdown();
}
}
}
package example_commands_test
import (
"context"
"fmt"
"github.com/redis/go-redis/v9"
)
func ExampleClient_set_get_all() {
ctx := context.Background()
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password docs
DB: 0, // use default DB
})
hashFields := []string{
"model", "Deimos",
"brand", "Ergonom",
"type", "Enduro bikes",
"price", "4972",
}
res1, err := rdb.HSet(ctx, "bike:1", hashFields).Result()
if err != nil {
panic(err)
}
fmt.Println(res1) // >>> 4
res2, err := rdb.HGet(ctx, "bike:1", "model").Result()
if err != nil {
panic(err)
}
fmt.Println(res2) // >>> Deimos
res3, err := rdb.HGet(ctx, "bike:1", "price").Result()
if err != nil {
panic(err)
}
fmt.Println(res3) // >>> 4972
cmdReturn := rdb.HGetAll(ctx, "bike:1")
res4, err := cmdReturn.Result()
if err != nil {
panic(err)
}
fmt.Println(res4)
// >>> map[brand:Ergonom model:Deimos price:4972 type:Enduro bikes]
type BikeInfo struct {
Model string `redis:"model"`
Brand string `redis:"brand"`
Type string `redis:"type"`
Price int `redis:"price"`
}
var res4a BikeInfo
if err := cmdReturn.Scan(&res4a); err != nil {
panic(err)
}
fmt.Printf("Model: %v, Brand: %v, Type: %v, Price: $%v\n",
res4a.Model, res4a.Brand, res4a.Type, res4a.Price)
// >>> Model: Deimos, Brand: Ergonom, Type: Enduro bikes, Price: $4972
}
func ExampleClient_hmget() {
ctx := context.Background()
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password docs
DB: 0, // use default DB
})
hashFields := []string{
"model", "Deimos",
"brand", "Ergonom",
"type", "Enduro bikes",
"price", "4972",
}
_, err := rdb.HSet(ctx, "bike:1", hashFields).Result()
if err != nil {
panic(err)
}
cmdReturn := rdb.HMGet(ctx, "bike:1", "model", "price")
res5, err := cmdReturn.Result()
if err != nil {
panic(err)
}
fmt.Println(res5) // >>> [Deimos 4972]
type BikeInfo struct {
Model string `redis:"model"`
Brand string `redis:"-"`
Type string `redis:"-"`
Price int `redis:"price"`
}
var res5a BikeInfo
if err := cmdReturn.Scan(&res5a); err != nil {
panic(err)
}
fmt.Printf("Model: %v, Price: $%v\n", res5a.Model, res5a.Price)
// >>> Model: Deimos, Price: $4972
}
func ExampleClient_hincrby() {
ctx := context.Background()
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password docs
DB: 0, // use default DB
})
hashFields := []string{
"model", "Deimos",
"brand", "Ergonom",
"type", "Enduro bikes",
"price", "4972",
}
_, err := rdb.HSet(ctx, "bike:1", hashFields).Result()
if err != nil {
panic(err)
}
res6, err := rdb.HIncrBy(ctx, "bike:1", "price", 100).Result()
if err != nil {
panic(err)
}
fmt.Println(res6) // >>> 5072
res7, err := rdb.HIncrBy(ctx, "bike:1", "price", -100).Result()
if err != nil {
panic(err)
}
fmt.Println(res7) // >>> 4972
}
func ExampleClient_incrby_get_mget() {
ctx := context.Background()
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password docs
DB: 0, // use default DB
})
res8, err := rdb.HIncrBy(ctx, "bike:1:stats", "rides", 1).Result()
if err != nil {
panic(err)
}
fmt.Println(res8) // >>> 1
res9, err := rdb.HIncrBy(ctx, "bike:1:stats", "rides", 1).Result()
if err != nil {
panic(err)
}
fmt.Println(res9) // >>> 2
res10, err := rdb.HIncrBy(ctx, "bike:1:stats", "rides", 1).Result()
if err != nil {
panic(err)
}
fmt.Println(res10) // >>> 3
res11, err := rdb.HIncrBy(ctx, "bike:1:stats", "crashes", 1).Result()
if err != nil {
panic(err)
}
fmt.Println(res11) // >>> 1
res12, err := rdb.HIncrBy(ctx, "bike:1:stats", "owners", 1).Result()
if err != nil {
panic(err)
}
fmt.Println(res12) // >>> 1
res13, err := rdb.HGet(ctx, "bike:1:stats", "rides").Result()
if err != nil {
panic(err)
}
fmt.Println(res13) // >>> 3
res14, err := rdb.HMGet(ctx, "bike:1:stats", "crashes", "owners").Result()
if err != nil {
panic(err)
}
fmt.Println(res14) // >>> [1 1]
}
using NRedisStack.Tests;
using StackExchange.Redis;
public class HashExample
{
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
}
}
你可以在文档中找到 哈希命令的完整列表。
值得注意的是,小哈希(即字段少、值小的哈希)在内存中以特殊方式编码,使其非常节省内存。
基本命令
查看 哈希命令的完整列表。
示例
- 存储 bike:1 被骑行、发生碰撞或更换所有者的次数计数器
> 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"
厌倦了使用 redis-cli?试试 Redis Insight - 适用于 Redis 的开发者 GUI。""" Code samples for Hash doc pages: https://redis.ac.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']
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']
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] } } }
package io.redis.examples.async; import io.lettuce.core.*; import io.lettuce.core.api.async.RedisAsyncCommands; import io.lettuce.core.api.StatefulRedisConnection; import java.util.*; import java.util.concurrent.CompletableFuture; public class HashExample { public void run() { RedisClient redisClient = RedisClient.create("redis://localhost:6379"); try (StatefulRedisConnection<String, String> connection = redisClient.connect()) { RedisAsyncCommands<String, String> asyncCommands = connection.async(); Map<String, String> bike1 = new HashMap<>(); bike1.put("model", "Deimos"); bike1.put("brand", "Ergonom"); bike1.put("type", "Enduro bikes"); bike1.put("price", "4972"); CompletableFuture<Void> setGetAll = asyncCommands.hset("bike:1", bike1).thenCompose(res1 -> { System.out.println(res1); // >>> 4 return asyncCommands.hget("bike:1", "model"); }).thenCompose(res2 -> { System.out.println(res2); // >>> Deimos return asyncCommands.hget("bike:1", "price"); }).thenCompose(res3 -> { System.out.println(res3); // >>> 4972 return asyncCommands.hgetall("bike:1"); }) .thenAccept(System.out::println) // >>> {type=Enduro bikes, brand=Ergonom, price=4972, model=Deimos} .toCompletableFuture(); CompletableFuture<Void> hmGet = setGetAll.thenCompose(res4 -> { return asyncCommands.hmget("bike:1", "model", "price"); }) .thenAccept(System.out::println) // [KeyValue[model, Deimos], KeyValue[price, 4972]] .toCompletableFuture(); CompletableFuture<Void> hIncrBy = hmGet.thenCompose(r -> { return asyncCommands.hincrby("bike:1", "price", 100); }).thenCompose(res6 -> { System.out.println(res6); // >>> 5072 return asyncCommands.hincrby("bike:1", "price", -100); }) .thenAccept(System.out::println) // >>> 4972 .toCompletableFuture(); CompletableFuture<Void> incrByGetMget = asyncCommands.hincrby("bike:1:stats", "rides", 1).thenCompose(res7 -> { System.out.println(res7); // >>> 1 return asyncCommands.hincrby("bike:1:stats", "rides", 1); }).thenCompose(res8 -> { System.out.println(res8); // >>> 2 return asyncCommands.hincrby("bike:1:stats", "rides", 1); }).thenCompose(res9 -> { System.out.println(res9); // >>> 3 return asyncCommands.hincrby("bike:1:stats", "crashes", 1); }).thenCompose(res10 -> { System.out.println(res10); // >>> 1 return asyncCommands.hincrby("bike:1:stats", "owners", 1); }).thenCompose(res11 -> { System.out.println(res11); // >>> 1 return asyncCommands.hget("bike:1:stats", "rides"); }).thenCompose(res12 -> { System.out.println(res12); // >>> 3 return asyncCommands.hmget("bike:1:stats", "crashes", "owners"); }) .thenAccept(System.out::println) // >>> [KeyValue[crashes, 1], KeyValue[owners, 1]] .toCompletableFuture(); CompletableFuture.allOf( hIncrBy, incrByGetMget).join(); } finally { redisClient.shutdown(); } } }
package example_commands_test import ( "context" "fmt" "github.com/redis/go-redis/v9" ) func ExampleClient_set_get_all() { ctx := context.Background() rdb := redis.NewClient(&redis.Options{ Addr: "localhost:6379", Password: "", // no password docs DB: 0, // use default DB }) hashFields := []string{ "model", "Deimos", "brand", "Ergonom", "type", "Enduro bikes", "price", "4972", } res1, err := rdb.HSet(ctx, "bike:1", hashFields).Result() if err != nil { panic(err) } fmt.Println(res1) // >>> 4 res2, err := rdb.HGet(ctx, "bike:1", "model").Result() if err != nil { panic(err) } fmt.Println(res2) // >>> Deimos res3, err := rdb.HGet(ctx, "bike:1", "price").Result() if err != nil { panic(err) } fmt.Println(res3) // >>> 4972 cmdReturn := rdb.HGetAll(ctx, "bike:1") res4, err := cmdReturn.Result() if err != nil { panic(err) } fmt.Println(res4) // >>> map[brand:Ergonom model:Deimos price:4972 type:Enduro bikes] type BikeInfo struct { Model string `redis:"model"` Brand string `redis:"brand"` Type string `redis:"type"` Price int `redis:"price"` } var res4a BikeInfo if err := cmdReturn.Scan(&res4a); err != nil { panic(err) } fmt.Printf("Model: %v, Brand: %v, Type: %v, Price: $%v\n", res4a.Model, res4a.Brand, res4a.Type, res4a.Price) // >>> Model: Deimos, Brand: Ergonom, Type: Enduro bikes, Price: $4972 } func ExampleClient_hmget() { ctx := context.Background() rdb := redis.NewClient(&redis.Options{ Addr: "localhost:6379", Password: "", // no password docs DB: 0, // use default DB }) hashFields := []string{ "model", "Deimos", "brand", "Ergonom", "type", "Enduro bikes", "price", "4972", } _, err := rdb.HSet(ctx, "bike:1", hashFields).Result() if err != nil { panic(err) } cmdReturn := rdb.HMGet(ctx, "bike:1", "model", "price") res5, err := cmdReturn.Result() if err != nil { panic(err) } fmt.Println(res5) // >>> [Deimos 4972] type BikeInfo struct { Model string `redis:"model"` Brand string `redis:"-"` Type string `redis:"-"` Price int `redis:"price"` } var res5a BikeInfo if err := cmdReturn.Scan(&res5a); err != nil { panic(err) } fmt.Printf("Model: %v, Price: $%v\n", res5a.Model, res5a.Price) // >>> Model: Deimos, Price: $4972 } func ExampleClient_hincrby() { ctx := context.Background() rdb := redis.NewClient(&redis.Options{ Addr: "localhost:6379", Password: "", // no password docs DB: 0, // use default DB }) hashFields := []string{ "model", "Deimos", "brand", "Ergonom", "type", "Enduro bikes", "price", "4972", } _, err := rdb.HSet(ctx, "bike:1", hashFields).Result() if err != nil { panic(err) } res6, err := rdb.HIncrBy(ctx, "bike:1", "price", 100).Result() if err != nil { panic(err) } fmt.Println(res6) // >>> 5072 res7, err := rdb.HIncrBy(ctx, "bike:1", "price", -100).Result() if err != nil { panic(err) } fmt.Println(res7) // >>> 4972 } func ExampleClient_incrby_get_mget() { ctx := context.Background() rdb := redis.NewClient(&redis.Options{ Addr: "localhost:6379", Password: "", // no password docs DB: 0, // use default DB }) res8, err := rdb.HIncrBy(ctx, "bike:1:stats", "rides", 1).Result() if err != nil { panic(err) } fmt.Println(res8) // >>> 1 res9, err := rdb.HIncrBy(ctx, "bike:1:stats", "rides", 1).Result() if err != nil { panic(err) } fmt.Println(res9) // >>> 2 res10, err := rdb.HIncrBy(ctx, "bike:1:stats", "rides", 1).Result() if err != nil { panic(err) } fmt.Println(res10) // >>> 3 res11, err := rdb.HIncrBy(ctx, "bike:1:stats", "crashes", 1).Result() if err != nil { panic(err) } fmt.Println(res11) // >>> 1 res12, err := rdb.HIncrBy(ctx, "bike:1:stats", "owners", 1).Result() if err != nil { panic(err) } fmt.Println(res12) // >>> 1 res13, err := rdb.HGet(ctx, "bike:1:stats", "rides").Result() if err != nil { panic(err) } fmt.Println(res13) // >>> 3 res14, err := rdb.HMGet(ctx, "bike:1:stats", "crashes", "owners").Result() if err != nil { panic(err) } fmt.Println(res14) // >>> [1 1] }
using NRedisStack.Tests; using StackExchange.Redis; public class HashExample { 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 开源版 7.4 中的新功能是能够为单个哈希字段指定过期时间或生存时间 (TTL) 值。此功能与键过期类似,并包含许多相似的命令。
使用以下命令为特定字段设置精确过期时间或 TTL 值
HEXPIRE
:设置剩余 TTL(秒)。HPEXPIRE
:设置剩余 TTL(毫秒)。HEXPIREAT
:将过期时间设置为以秒指定的1时间戳。HPEXPIREAT
:将过期时间设置为以毫秒指定的时间戳。
使用以下命令检索特定字段的精确过期时间或剩余 TTL
HEXPIRETIME
:获取以秒为单位的时间戳形式的过期时间。HPEXPIRETIME
:获取以毫秒为单位的时间戳形式的过期时间。HTTL
:获取剩余 TTL(秒)。HPTTL
:获取剩余 TTL(毫秒)。
使用以下命令移除特定字段的过期设置
HPERSIST
:移除过期设置。
常见字段过期用例
-
事件跟踪:使用哈希键存储过去一小时的事件。将每个事件的 TTL 设置为一小时。使用
HLEN
计算过去一小时的事件数量。 -
欺诈检测:创建一个包含事件小时计数器的哈希。将每个字段的 TTL 设置为 48 小时。查询哈希以获取过去 48 小时内每小时的事件数量。
-
客户会话管理:将客户数据存储在哈希键中。为每个会话创建一个新的哈希键,并在客户的哈希键中添加一个会话字段。当会话过期时,自动使会话键和客户哈希键中的会话字段过期。
-
活跃会话跟踪:将所有活跃会话存储在哈希键中。设置每个会话的 TTL,使其在不活动后自动过期。使用
HLEN
计算活跃会话的数量。
字段过期示例
官方客户端库尚未提供对哈希字段过期的支持,但你现在可以使用 Python (redis-py) 和 Java (Jedis) 客户端库的测试版来测试哈希字段过期功能。
以下是一些演示如何使用字段过期的 Python 示例。
考虑一个用于存储传感器数据的哈希数据集,其结构如下
event = {
'air_quality': 256,
'battery_level':89
}
r.hset('sensor:sensor1', mapping=event)
在下面的示例中,其字段过期后,你可能需要刷新 sensor:sensor1
键。
设置并检索哈希中多个字段的 TTL
# set the TTL for two hash fields to 60 seconds
r.hexpire('sensor:sensor1', 60, 'air_quality', 'battery_level')
ttl = r.httl('sensor:sensor1', 'air_quality', 'battery_level')
print(ttl)
# prints [60, 60]
设置并检索哈希字段以毫秒为单位的 TTL
# set the TTL of the 'air_quality' field in milliseconds
r.hpexpire('sensor:sensor1', 60000, 'air_quality')
# and retrieve it
pttl = r.hpttl('sensor:sensor1', 'air_quality')
print(pttl)
# prints [59994] # your actual value may vary
设置并检索哈希字段的过期时间戳
# set the expiration of 'air_quality' to now + 24 hours
# (similar to setting the TTL to 24 hours)
r.hexpireat('sensor:sensor1',
datetime.now() + timedelta(hours=24),
'air_quality')
# and retrieve it
expire_time = r.hexpiretime('sensor:sensor1', 'air_quality')
print(expire_time)
# prints [1717668041] # your actual value may vary
性能
大多数 Redis 哈希命令是 O(1) 的。
少数命令,例如 HKEYS
、HVALS
、HGETALL
以及大多数与过期相关的命令,是 O(n) 的,其中 n 是字段-值对的数量。
限制
每个哈希最多可以存储 4,294,967,295 (2^32 - 1) 个字段-值对。实际上,你的哈希仅受托管 Redis 部署的虚拟机上的总内存限制。
了解更多
- Redis 哈希详解 是一个简短、全面的视频讲解,介绍了 Redis 哈希。
- Redis 大学 RU101 详细介绍了 Redis 哈希。