DEV Community

Cover image for StackExchange.Redis: Usando estruturas de dados Redis Lists
Paulo Walraven
Paulo Walraven

Posted on

2

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

Sentry image

Hands-on debugging session: instrument, monitor, and fix

Join Lazar for a hands-on session where you’ll build it, break it, debug it, and fix it. You’ll set up Sentry, track errors, use Session Replay and Tracing, and leverage some good ol’ AI to find and fix issues fast.

RSVP here →

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay