StackExchange.Redis: Usando estruturas de dados Redis Lists

paulowalravendev

Paulo Walraven

Posted on February 19, 2023

StackExchange.Redis: Usando estruturas de dados Redis Lists

Introdução

Redis Lists são listas duplamente vinculadas(linked list) que permitem que você empurre e pop da frente(head) e da cauda(tail). Isso permite que você crie o que são essencialmente filas e pilhas de Redis Strings. A biblioteca StackExchange.Redis fornece uma interface intuitiva para trabalhar com listas no IDatabase.

Redis List na prática

As listas são listas duplamente vinculadas (linked list), o que significa que você pode empurrar ou pular de qualquer lado da lista. No entanto, qualquer tipo de acesso indexado torna-se uma operação O(N), onde N é o número de elementos que você precisa percorrer para alcançar o índice.

Adicionando itens na lista

Vamos adicionar algumas linguagens de programação para o lado esquerdo da lista(head).

var programmingLanguages = new string[] { "C#", "F#", "Elixir", "Java", "JavaScript", "Pascal" };
await database.ListLeftPushAsync(programmingLanguagesKey, programmingLanguages.Select(p => (RedisValue)p).ToArray());
Enter fullscreen mode Exit fullscreen mode

Agora vamos tentar imprimir o primeiro elemento desta lista. As listas são indexadas da esquerda para a direita, consequentemente a última linguagem de programação que adicionamos para a esquerda, será o 0º índice "Pascal”

var lastProgramingLanguage = await database.ListGetByIndexAsync(programmingLanguagesKey, 0);
Console.WriteLine($"The last programming language in the list is: {lastProgramingLanguage}");
Enter fullscreen mode Exit fullscreen mode
// output
The last programming language in the list is: Pascal
Enter fullscreen mode Exit fullscreen mode

E se acessássemos o final da lista, com o índice -1, obteríamos o primeiro elemento que colocamos no lado esquerdo da lista, "C#":

var firstProgramingLanguage = await database.ListGetByIndexAsync(programmingLanguagesKey, -1);
Console.WriteLine($"The first programming language in the list is: {firstProgramingLanguage}");
Enter fullscreen mode Exit fullscreen mode
The first programming language in the list is: C#
Enter fullscreen mode Exit fullscreen mode

Em nossa lista de empresas de tecnologias, agora vamos adicionar a direita. Como estamos pressionando para a direita, o item em questão é adicionado ao final da lista, tornando-o o último elemento da lista se iterarmos na lista.

var technologyCompanies = new string[] { "Microsoft", "Oracle", "Apple", "IBM" };
await database.ListRightPushAsync(technologyCompaniesKey, technologyCompanies.Select(p => (RedisValue)p).ToArray());
Enter fullscreen mode Exit fullscreen mode

Agora, se tentarmos acessar o primeiro elemento da lista, obteremos o primeiro elemento que empurramos para a direita, "Microsoft".

var firstTechnologyCompany = await database.ListGetByIndexAsync(technologyCompaniesKey, 0);
Console.WriteLine($"The first technology in the list is: {firstTechnologyCompany}");
Enter fullscreen mode Exit fullscreen mode
// output
The first technology in the list is: Microsoft
Enter fullscreen mode Exit fullscreen mode

Por outro lado, se acessarmos o último elemento, obteremos "IBM"

var lastTechnologyCompany = await database.ListGetByIndexAsync(technologyCompaniesKey, -1);
Console.WriteLine($"The last technology in the list is: {lastTechnologyCompany}");
Enter fullscreen mode Exit fullscreen mode
// output
The last technology in the list is: IBM
Enter fullscreen mode Exit fullscreen mode

Enumerar uma Lista

Para enumerar uma lista, você pode usar o método ListRange. Se você passar um índice de início, o intervalo começará a partir daí, e se você passar um índice de parada, ele parará ali, se você não passar nem um início nem um fim, ele irá puxar para trás toda a lista.

Console.WriteLine($"Programming language index 0 to -1: {string.Join(", ", await database.ListRangeAsync(programmingLanguagesKey))}");
Console.WriteLine($"Technology companies index 0 to -2: {string.Join(", ", await database.ListRangeAsync(technologyCompaniesKey, 0, -2))}");
Enter fullscreen mode Exit fullscreen mode
// output
Programming language index 0 to -1: Pascal, JavaScript, Java, Elixir, F#, C#
Technology companies index 0 to -2: Microsoft, Oracle, Apple
Enter fullscreen mode Exit fullscreen mode

Mover elementos entre listas

Você também pode transferir elementos entre listas usando o método ListMove. Isso aceita duas chaves de lista, bem como o lado de origem e o lado de destino. Estes são os lados da lista de onde você irá pular e empurrar, respectivamente.

await database.ListMoveAsync(programmingLanguagesKey, technologyCompaniesKey, ListSide.Right, ListSide.Left);
Enter fullscreen mode Exit fullscreen mode
127.0.0.1:6379> lrange programming-languages 0 -1
1) "Pascal"
2) "JavaScript"
3) "Java"
4) "Elixir"
5) "F#"
127.0.0.1:6379> lrange technology-companies 0 -1
1) "C#"
2) "Microsoft"
3) "Oracle"
4) "Apple"
5) "IBM"
Enter fullscreen mode Exit fullscreen mode

Lista como uma fila

Você pode usar uma lista Redis como uma fila FIFO de fato pressionando e abrindo de diferentes lados. Convencionalmente, você adicionar para a esquerda, removeria para a direita:

await database.ListLeftPushAsync(programmingLanguagesKey, "Rust");
Console.WriteLine($"Dequeued: {await database.ListRightPopAsync(programmingLanguagesKey)}");
Enter fullscreen mode Exit fullscreen mode
// output
Dequeued: F#

127.0.0.1:6379> lrange programming-languages 0 -1
1) "Rust"
2) "Pascal"
3) "JavaScript"
4) "Java"
5) "Elixir"
Enter fullscreen mode Exit fullscreen mode

Lista como uma pilha

Você também pode fazer com que suas listas atuem como pilhas LIFO, pressionando e retirando das mesmas, por convenção, você normalmente usaria o lado esquerdo.

await database.ListLeftPushAsync(technologyCompaniesKey, "JetBrains");
Console.WriteLine($"Popping: {await database.ListLeftPopAsync(technologyCompaniesKey)}");
Enter fullscreen mode Exit fullscreen mode
// output
Popping: JetBrains
Enter fullscreen mode Exit fullscreen mode

Pesquisando na lista

As listas Redis também permitem encontrar o índice de um item específico usando o método ListPosition.

Console.WriteLine($"Position of Java: {await database.ListPositionAsync(programmingLanguagesKey, "Java")}");
Enter fullscreen mode Exit fullscreen mode
// ouput
Position of Java: 3
Enter fullscreen mode Exit fullscreen mode

Tamanho da Lista

Você usa o método ListLength para determinar o tamanho de uma determinada lista.

Console.WriteLine($"There are {await database.ListLengthAsync(technologyCompaniesKey)} technology companies in our list");
Enter fullscreen mode Exit fullscreen mode
// output
There are 5 technology companies in our list
Enter fullscreen mode Exit fullscreen mode

Código completo

using StackExchange.Redis;
using System.Diagnostics;

var options = new ConfigurationOptions
{
    EndPoints = new EndPointCollection { "localhost:6379" }
};

var conn = ConnectionMultiplexer.Connect(options);
var database = conn.GetDatabase();

var programmingLanguagesKey = "programming-languages";
var technologyCompaniesKey = "technology-companies";
var keysToDelete = new string[] { programmingLanguagesKey, technologyCompaniesKey };
await database.KeyDeleteAsync(keysToDelete.Select(k => (RedisKey)k).ToArray());

var programmingLanguages = new string[] { "C#", "F#", "Elixir", "Java", "JavaScript", "Pascal" };
await database.ListLeftPushAsync(programmingLanguagesKey, programmingLanguages.Select(p => (RedisValue)p).ToArray());

var lastProgramingLanguage = await database.ListGetByIndexAsync(programmingLanguagesKey, 0);
Console.WriteLine($"The last programming language in the list is: {lastProgramingLanguage}");

var firstProgramingLanguage = await database.ListGetByIndexAsync(programmingLanguagesKey, -1);
Console.WriteLine($"The first programming language in the list is: {firstProgramingLanguage}");

var technologyCompanies = new string[] { "Microsoft", "Oracle", "Apple", "IBM" };
await database.ListRightPushAsync(technologyCompaniesKey, technologyCompanies.Select(p => (RedisValue)p).ToArray());

var firstTechnologyCompany = await database.ListGetByIndexAsync(technologyCompaniesKey, 0);
Console.WriteLine($"The first technology in the list is: {firstTechnologyCompany}");

var lastTechnologyCompany = await database.ListGetByIndexAsync(technologyCompaniesKey, -1);
Console.WriteLine($"The last technology in the list is: {lastTechnologyCompany}");

Console.WriteLine($"Programming language index 0 to -1: {string.Join(", ", await database.ListRangeAsync(programmingLanguagesKey))}");
Console.WriteLine($"Technology companies index 0 to -2: {string.Join(", ", await database.ListRangeAsync(technologyCompaniesKey, 0, -2))}");

await database.ListMoveAsync(programmingLanguagesKey, technologyCompaniesKey, ListSide.Right, ListSide.Left);

await database.ListLeftPushAsync(programmingLanguagesKey, "Rust");
Console.WriteLine($"Dequeued: {await database.ListRightPopAsync(programmingLanguagesKey)}");

await database.ListLeftPushAsync(technologyCompaniesKey, "JetBrains");
Console.WriteLine($"Popping: {await database.ListLeftPopAsync(technologyCompaniesKey)}");

Console.WriteLine($"Position of Java: {await database.ListPositionAsync(programmingLanguagesKey, "Java")}");

Console.WriteLine($"There are {await database.ListLengthAsync(technologyCompaniesKey)} technology companies in our list");
Enter fullscreen mode Exit fullscreen mode
💖 💪 🙅 🚩
paulowalravendev
Paulo Walraven

Posted on February 19, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related