Introduction to Redis Sets

Introduction to Redis Sets

Welcome! Today, we are stepping into the fascinating world of Redis sets. As you may remember, Redis is an advanced key-value store where keys can contain different types of data structures, such as strings, lists, and even sets. Understanding sets in Redis will allow you to manage unique collections of data efficiently, whether you are tracking unique user visits to a website or managing distinct tags associated with articles.

What You'll Learn

In this lesson, you will learn how to use sets in Redis with C++. We'll explore the fundamental operations for managing sets, including adding items, retrieving members, counting elements, and removing items from a set.

Redis sets are collections of unique, unordered elements. They are highly optimized for operations like checking if an item exists, adding or removing items, and retrieving all members.

Adding and Retrieving Set Members

Let's start by connecting to your Redis server and learning how to add items to a set and retrieve all its members:

C++
#include <boost/redis.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/detached.hpp>
#include <boost/asio/consign.hpp>
#include <iostream>
#include <vector>
#include <string>

#include <boost/redis/src.hpp>

namespace net = boost::asio;
using boost::redis::connection;
using boost::redis::config;
using boost::redis::logger;
using boost::redis::request;
using boost::redis::response;

int main() {
    try {
        net::io_context ioc;

        auto conn = std::make_shared<connection>(ioc.get_executor());

        config cfg;
        conn->async_run(cfg, logger{logger::level::disabled},
                        net::consign(net::detached, conn));

        request req;
        req.push("SADD", "countries", "USA", "Canada", "UK", "USA");
        req.push("SMEMBERS", "countries");

        response<std::int64_t, std::vector<std::string>> resp;

        conn->async_exec(req, resp,
            [conn, &resp](boost::system::error_code ec, std::size_t) {
                if (!ec) {
                    const auto& sadd_res = std::get<0>(resp);
                    if (sadd_res) {
                        std::cout << "Elements added: " << sadd_res.value() << "\n";
                    }

                    const auto& smembers_res = std::get<1>(resp);
                    if (smembers_res) {
                        const auto& countries = smembers_res.value();
                        std::cout << "Countries in the set: ";
                        for (const auto& country : countries) {
                            std::cout << country << " ";
                        }
                        std::cout << "\n";
                    }
                } else {
                    std::cerr << "Error executing Redis commands: " << ec.message() << "\n";
                }
                conn->cancel();
            });

        ioc.run();
    } catch (const std::exception& e) {
        std::cerr << "Exception: " << e.what() << "\n";
        return 1;
    }
    return 0;
}

This example shows how to handle sets in Redis and demonstrates the asynchronous approach required when using Boost.Redis.

Let's break down the code:

  • We start by setting up the connection infrastructure: we create an io_context, which manages asynchronous operations, and a connection object that represents our Redis connection.
  • The async_run method establishes and maintains the connection to Redis asynchronously. It uses net::consign to keep the connection alive throughout the async operations.
  • We create a request object and add commands to it using push(). In this case, we add items to a set called countries using the SADD command, including a duplicate USA. Then, we add the SMEMBERS command to retrieve all members.
  • We declare a response object with template parameters matching our commands: std::int64_t for the SADD result (number of elements added) and std::vector<std::string> for SMEMBERS (the list of countries).
  • The async_exec method executes our batched commands asynchronously. When the operation completes, the callback function is invoked.
  • Inside the callback, we check for errors using error_code. If successful, we access each response using std::get<N>(), where N is the command index.
  • Each response element is an optional value, so we check if it has a value before accessing it with .value().
  • The output will show that three elements were added (the duplicate USA was not counted) and display the countries: USA Canada UK. Note that the order of elements in the set is not guaranteed.
  • Finally, we call ioc.run(), which processes all asynchronous operations.
Sign up

Join the 1M+ learners on CodeSignal

Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal