redis++使用: hmset 与 hmget

1.hmget 接口

hmget 是一个 Redis C++ 客户端库(redis-plus-plus)中的函数,用于批量获取 Hash 类型数据中的多个字段值。

接口说明

cpp 复制代码
template <typename Input, typename Output>
inline void Redis::hmget(const StringView &key, Input first, Input last, Output output)

参数解释:

  • key: Hash 的键名
  • first, last: 输入迭代器范围,指定要获取的字段名列表
  • output: 输出迭代器,用于接收返回的值

使用示例

示例 1: 使用 vector 存储字段名和结果

cpp 复制代码
#include <sw/redis++/redis++.h>
#include <vector>
#include <string>
#include <iostream>

using namespace sw::redis;

int main() {
    // 连接 Redis
    auto redis = Redis("tcp://127.0.0.1:6379");
    
    // 假设 Redis 中有一个 hash: user:1001
    // HSET user:1001 name "张三" age "25" email "zhangsan@example.com"
    
    // 定义要获取的字段名
    std::vector<std::string> fields = {"name", "age", "email"};
    
    // 准备接收结果的容器
    std::vector<OptionalString> results;
    
    // 调用 hmget
    redis.hmget("user:1001", fields.begin(), fields.end(), std::back_inserter(results));
    
    // 处理结果
    for (size_t i = 0; i < fields.size(); ++i) {
        if (results[i]) {
            std::cout << fields[i] << ": " << *results[i] << std::endl;
        } else {
            std::cout << fields[i] << ": (nil)" << std::endl;
        }
    }
    
    return 0;
}

示例 2: 使用数组

cpp 复制代码
// 使用 C 风格数组
const char* fields[] = {"name", "age", "email"};
std::vector<OptionalString> results;

redis.hmget("user:1001", 
            std::begin(fields), 
            std::end(fields), 
            std::back_inserter(results));

示例 3: 直接指定字段列表

cpp 复制代码
// 使用 initializer_list
std::vector<std::string> fields = {"field1", "field2", "field3"};
std::vector<OptionalString> values;

redis.hmget("myhash", 
            fields.begin(), 
            fields.end(), 
            std::back_inserter(values));

// 访问结果
if (values[0]) {
    std::cout << "field1 = " << *values[0] << std::endl;
}

关键点说明

  1. OptionalString : 返回值类型,因为字段可能不存在,所以用 Optional 包装
    • 如果字段存在:OptionalString 包含实际值
    • 如果字段不存在:OptionalString 为空(类似 nullptr)

OptionalString 不是 C++ 标准库的类型,而是 redis-plus-plus 库自己定义的类型。 在

redis-plus-plus 中,OptionalString 通常定义为:

cpp 复制代码
//Optional 是redis自定义的一个模板类
using OptionalString = Optional<std::string>;
  1. 迭代器模式:

    • Input 可以是任何输入迭代器(vector、list、数组等的 begin/end)
    • Output 通常是插入迭代器(如 std::back_inserter
  2. 结果顺序: 返回值的顺序与请求字段的顺序一致

  3. 检查空值 : 使用前一定要检查 OptionalString 是否有值

2.hmset 接口

HMSET 是 Redis 中用于批量设置 Hash 字段值的命令。在 redis-plus-plus 库中有多种使用方式。

基本用法示例

好的,我用和之前 hmget 一样的例子来讲解 hmset

HMSET 使用示例

示例 1: 使用 initializer_list(最常用)

cpp 复制代码
#include <sw/redis++/redis++.h>
#include <string>
#include <iostream>

using namespace sw::redis;

int main() {
    auto redis = Redis("tcp://127.0.0.1:6379");
    
    // 批量设置 user:1001 的多个字段
    redis.hmset("user:1001", {
        {"name", "张三"},
        {"age", "25"},
        {"email", "zhangsan@example.com"}
    });
    
    std::cout << "数据设置成功!" << std::endl;
    
    return 0;
}

示例 2: 使用 vector of pairs

cpp 复制代码
#include <sw/redis++/redis++.h>
#include <vector>
#include <string>

using namespace sw::redis;

int main() {
    auto redis = Redis("tcp://127.0.0.1:6379");
    
    // 准备要设置的字段和值
    std::vector<std::pair<std::string, std::string>> user_data;
    user_data.push_back({"name", "李四"});
    user_data.push_back({"age", "30"});
    user_data.push_back({"email", "lisi@example.com"});
    user_data.push_back({"phone", "13800138000"});
    
    // 批量设置
    redis.hmset("user:1002", user_data.begin(), user_data.end());
    
    return 0;
}

示例 3: 使用 unordered_map

cpp 复制代码
#include <sw/redis++/redis++.h>
#include <unordered_map>
#include <string>

using namespace sw::redis;

int main() {
    auto redis = Redis("tcp://127.0.0.1:6379");
    
    // 使用 map 存储数据
    std::unordered_map<std::string, std::string> user_info;
    user_info["name"] = "王五";
    user_info["age"] = "28";
    user_info["city"] = "上海";
    
    // 批量设置 - 使用迭代器
    redis.hmset("user:1003", user_info.begin(), user_info.end());
    
    return 0;
}

示例 4: HMSET + HMGET 完整流程

cpp 复制代码
#include <sw/redis++/redis++.h>
#include <vector>
#include <string>
#include <iostream>

using namespace sw::redis;

int main() {
    auto redis = Redis("tcp://127.0.0.1:6379");
    
    // ========== 第一步:批量设置数据 ==========
    redis.hmset("user:1001", {
        {"name", "张三"},
        {"age", "25"},
        {"email", "zhangsan@example.com"},
        {"city", "北京"}
    });
    
    std::cout << "=== 数据已设置 ===" << std::endl;
    
    // ========== 第二步:批量读取数据 ==========
    std::vector<std::string> fields = {"name", "age", "email", "city"};
    std::vector<OptionalString> results;
    
    redis.hmget("user:1001", 
                fields.begin(), 
                fields.end(), 
                std::back_inserter(results));
    
    // ========== 第三步:处理结果 ==========
    std::cout << "\n=== 读取结果 ===" << std::endl;
    for (size_t i = 0; i < fields.size(); ++i) {
        std::cout << fields[i] << ": ";
        if (results[i]) {
            std::cout << *results[i] << std::endl;
        } else {
            std::cout << "(nil)" << std::endl;
        }
    }
    
    return 0;
}

输出:

复制代码
=== 数据已设置 ===

=== 读取结果 ===
name: 张三
age: 25
email: zhangsan@example.com
city: 北京

示例 5: 动态构建数据后设置

cpp 复制代码
#include <sw/redis++/redis++.h>
#include <map>
#include <string>
#include <iostream>

using namespace sw::redis;

int main() {
    auto redis = Redis("tcp://127.0.0.1:6379");
    
    // 动态构建用户数据
    std::map<std::string, std::string> user_data;
    
    user_data["name"] = "赵六";
    user_data["age"] = "35";
    user_data["department"] = "技术部";
    user_data["position"] = "工程师";
    
    // 批量设置到 Redis
    std::string user_key = "user:1004";
    redis.hmset(user_key, user_data.begin(), user_data.end());
    
    std::cout << "用户数据已保存到: " << user_key << std::endl;
    
    // 验证:读取其中一个字段
    auto name = redis.hget(user_key, "name");
    if (name) {
        std::cout << "姓名: " << *name << std::endl;
    }
    
    return 0;
}

HMSET 接口形式总结

redis-plus-plus 提供了多种 hmset 重载:

cpp 复制代码
// 形式1: 使用 initializer_list(最简洁)
redis.hmset("key", {
    {"field1", "value1"},
    {"field2", "value2"}
});

// 形式2: 使用迭代器范围
redis.hmset("key", first_iterator, last_iterator);
// 其中 iterator 指向 pair<string, string> 或类似结构

// 形式3: 使用 template(支持各种容器)
template <typename Input>
void hmset(const StringView &key, Input first, Input last);

关键点

  1. 返回值 : hmset 返回 void,失败时抛出异常
  2. 覆盖行为: 如果字段已存在,新值会覆盖旧值
  3. 原子性: 所有字段要么全部设置成功,要么全部失败
  4. 异常处理 : 需要捕获 ReplyErrorTimeoutError 等异常

带异常处理的完整示例

cpp 复制代码
#include <sw/redis++/redis++.h>
#include <string>
#include <iostream>

using namespace sw::redis;

int main() {
    try {
        auto redis = Redis("tcp://127.0.0.1:6379");
        
        // 批量设置
        redis.hmset("user:1001", {
            {"name", "张三"},
            {"age", "25"},
            {"email", "zhangsan@example.com"}
        });
        
        std::cout << "设置成功!" << std::endl;
        
    } catch (const ReplyError &err) {
        std::cerr << "Redis 命令错误: " << err.what() << std::endl;
    } catch (const TimeoutError &err) {
        std::cerr << "Redis 超时: " << err.what() << std::endl;
    } catch (const Error &err) {
        std::cerr << "Redis 错误: " << err.what() << std::endl;
    }
    
    return 0;
}
相关推荐
xu_ws4 小时前
redis的io多路复用和Java NIO的区别
java·redis·nio
艾莉丝努力练剑4 小时前
【Linux网络】Linux 网络编程:应用层自定义协议与序列化(3):网络计算器实现和守护进程
linux·运维·服务器·网络·c++·计算机网络·安全
千寻girling4 小时前
周日那天参加的力扣周赛... —— 10号
java·javascript·c++·python·算法·leetcode·职场和发展
Devin~Y4 小时前
大厂Java面试实录:Spring Boot微服务 + Redis/Kafka + Prometheus/Jaeger + RAG/Agent(小Y水货版)
java·spring boot·redis·spring cloud·kafka·prometheus·jaeger
研究点啥好呢4 小时前
dji机器人SLAM算法工程师 面试题精选:10道高频考题+答案解析
c++·算法·机器人·slam·dji
jllllyuz4 小时前
VC++ 读写 Excel 文件实现
开发语言·c++·excel
小小编程能手4 小时前
C++文件从操作:
开发语言·c++
茉莉玫瑰花茶4 小时前
C++ 17 详细特性解析(6)
开发语言·c++
东方.既白4 小时前
QML与C++炫酷界面交互DEMO
开发语言·c++·交互
承渊政道4 小时前
【贪心算法】(经典实战应用解析(一):柠檬水找零、将数组和减半的最少操作次数、最大数、摆动序列)
数据结构·c++·学习·算法·leetcode·贪心算法·排序算法