目录
上篇文章我们讲完了 cpp-redis 的 基本设置 问题[Redis#10] scan | db_0 | redis_cli | RESP | C++-redis启动教程,这篇文章 我们将对于通用命令 进行进一步的讲解~
我们提到了redis-plus-plus
,它是一个基于 hiredis
实现的C++库,用于操作Redis数据库。具有与Redis原生命令几乎完全一致的接口风格,并且易于使用。本文将详细介绍如何使用这个库来执行常见的Redis操作。
接口特点
- 参数传递:当函数需要接受多个值时,支持通过初始化列表或迭代器对进行传递。
- 返回多数据:对于需要表示多个数据的情况,通常可以通过插入迭代器将结果添加到容器中。
- 无效值处理 :在涉及无效值的情况下,通常会使用
std::optional
来表示。
通用接口
参考文档github--redis-plus-plus/src/sw/redis++ /redis.cpp
redis-plus-plus
支持多种Redis通用命令,包括:
- get/set:获取/设置键值对。
- exists:检查键是否存在。
- del:删除键。
- keys:搜索符合条件的键。
- expire/ttl:设置/查询键的过期时间
- type:获取键对应的值类型。
示例代码
#include <iostream>
#include <sw/redis++/redis++.h>
int main() {
// 创建Redis对象,并指定服务器地址和端口
sw::redis::Redis redis("tcp://127.0.0.1:6379");
// 设置键值对
redis.set("key1", "value1");
std::string value = redis.get("key1").value_or("default_value");
std::cout << "Value of key1: " << value << std::endl;
// 检查键是否存在
bool exists = (redis.exists("key1") == 1);
std::cout << "Key1 exists: " << (exists ? "Yes" : "No") << std::endl;
// 删除键
redis.del("key1");
// 搜索符合条件的键
std::vector<std::string> keys;
auto it = std::back_inserter(keys);
redis.keys("*", it);
for (const auto& key : keys) {
std::cout << "Found key: " << key << std::endl;
}
// 设置键的过期时间
redis.set("key2", "value2");
redis.expire("key2", 10); // 10秒后过期
long long ttl = redis.ttl("key2");
std::cout << "TTL of key2: " << ttl << " seconds" << std::endl;
// 获取键的类型
std::string type = redis.type("key2");
std::cout << "Type of key2: " << type << std::endl;
return 0;
}
运行
C++字符串类型
- std::string:可修改的字符串,既能读也能写。
- std::string_view :只读的字符串视图,不能修改,针对只读操作效率更高。在C++17中引入。
示例
#include <iostream>
#include <string>
#include <string_view>
int main() {
std::string str = "Hello, World!";
std::string_view view(str);
// 只读操作
std::cout << "String View: " << view << std::endl;
// 尝试修改会引发编译错误
// view[0] = 'h'; // 错误:std::string_view是只读的
return 0;
}
运行
std::optional的使用
- std::optional:可以表示"非法值"或"无效值",例如在Redis中查询不到键时返回
nil
。 - 在C++14中通过
boost
库引入了optional
类型,在C++17中被纳入标准库。
示例
#include <iostream>
#include <optional>
#include <string>
int main() {
std::optional<std::string> value1 = "Hello";
std::optional<std::string> value2; // 未初始化
std::optional<std::string> value3 = "World";
std::optional<std::string> value4; // 未初始化
if (value1) {
std::cout << *value1 << std::endl; // 输出: Hello
}
if (value3) {
std::cout << *value3 << std::endl; // 输出: World
}
// 处理未初始化的情况
if (!value2) {
std::cout << "Value2 is not set" << std::endl;
}
if (!value4) {
std::cout << "Value4 is not set" << std::endl;
}
return 0;
}
运行
keys
命令的使用
keys
函数用于 搜索所有符合条件的键,其声明如下:
template <typename Output>
void keys(const StringView &pattern, Output output);
- 第一个参数
pattern
是匹配模式。 - 第二个参数
output
是一个插入迭代器,用于获取符合条件的键,元素类型可以是std::string
或StringView
。
示例代码
int main() {
sw::redis::Redis redis("tcp://127.0.0.1:6379");
redis.flushall(); // 清空数据库
// 设置一些键值对
redis.set("key1", "111");
redis.set("key2", "222");
redis.set("key3", "222");
redis.set("key4", "222");
// 准备存储结果的容器
std::vector<std::string> result;
auto it = std::back_inserter(result); // 创建一个尾部插入迭代器
// 执行keys命令
redis.keys("*", it);
// 输出结果
for (auto& ret : result) {
std::cout << ret << std::endl;
}
return 0;
}
输出结果
插入迭代器
插入迭代器是一种专门用于将元素插入到容器中的迭代器。主要种类包括:
std::front_insert_iterator
:在容器头部插入。std::back_insert_iterator
:在容器尾部插入。std::insert_iterator
:在容器的任意位置插入。
这类迭代器的特性在于++
和--
操作无效,核心操作是operator=
。
自定义插入迭代器示例
下面展示了一个简单的自定义插入迭代器的实现,用于向std::vector
中插入元素:
template <typename T>
class InsertIterator {
public:
// 构造函数,保存容器引用和插入位置的迭代器
InsertIterator(std::vector<T>& vec, typename std::vector<T>::iterator pos)
: vec_(vec), pos_(pos) {}
// 重载赋值操作符,实现插入逻辑
InsertIterator& operator=(const T& value) {
pos_ = vec_.insert(pos_, value);
return *this;
}
// 重载前置和后置增加操作符,因为插入操作不改变迭代器位置
InsertIterator& operator++() { return *this; }
InsertIterator& operator++(int) { return *this; }
// 重载解引用操作符,以便可以链式调用
InsertIterator& operator*() { return *this; }
private:
std::vector<T>& vec_;
typename std::vector<T>::iterator pos_;
};
标准库提供的插入迭代器接口
要获取对应容器的插入迭代器,可以使用标准库提供的接口:
std::front_inserter(container);
std::back_inserter(container);
std::inserter(container, position);
对于像std::vector
这样的容器,由于提供了头尾删除接口,可以方便地使用front_inserter
或back_inserter
。对于如std::set
这样不支持随机访问的容器,则通常只能使用inserter
。
优点:可以简化从Redis返回结果集到各种不同容器的转换过程,无需为每种容器类型编写单独的处理逻辑