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;
}
相关推荐
2401_895521342 小时前
Linux下安装Redis
linux·运维·redis
handler012 小时前
拒绝权限报错!三分钟掌握 Linux 权限管理
linux·c语言·c++·笔记·学习
ward RINL3 小时前
redis分页查询
数据库·redis·缓存
Treh UNFO3 小时前
Redis-配置文件
数据库·redis·oracle
iNgs IMAC3 小时前
Redis之Redis事务
java·数据库·redis
oLLI PILO3 小时前
Redis连接池
数据库·redis·缓存
t***5443 小时前
如何在Dev-C++中选择Clang编译器
开发语言·c++
汉克老师4 小时前
GESP2023年9月认证C++三级( 第一部分选择题(9-15))
c++·gesp三级·gesp3级
heRs BART4 小时前
Redis简介、常用命令及优化
数据库·redis·缓存