Cheatsheet

Como gerenciar conjuntos ordenados no Redis

Published on April 10, 2020
Default avatar

By Mark Drake

Manager, Developer Education

Português
Como gerenciar conjuntos ordenados no Redis

Introdução

O Redis é um repositório de dados de valor-chave na memória, de código aberto. No Redis, os conjuntos ordenados são um tipo de dados semelhante aos conjuntos, sendo ambos grupos não repetidos de strings. A diferença é que cada membro de um conjunto ordenado está associado a uma pontuação, permitindo que eles sejam ordenados da pontuação menor para a maior. Como nos conjuntos, cada membro de um conjunto ordenado deve ser único, embora vários membros possam compartilhar a mesma pontuação.

Este tutorial explica como criar conjuntos ordenados, recuperar e remover seus membros e criar novos conjuntos ordenados a partir de dados existentes.

Como usar este guia

Este guia foi escrito como uma folha de referências com exemplos independentes. Encorajamos você a ir direto para as seções que sejam relevantes para a tarefa que está tentando completar.

Os comandos mostrados neste guia foram testados em um servidor Ubuntu 18.04 executando a versão 4.0.9 do Redis. Para configurar um ambiente semelhante, siga o Passo 1 de nosso guia sobre Como instalar e proteger o Redis no Ubuntu 18.04. Vamos demonstrar como esses comandos se comportam executando-os com o redis-cli, a interface de linha de comando do Redis. Note que caso esteja usando uma interface diferente do Redis — Redli, por exemplo — o resultado exato de certos comandos pode diferir.

De maneira alternativa, você pode provisionar uma instância de banco de dados gerenciado do Redis para testar esses comandos, mas note que, dependendo do nível de controle permitido pelo seu provedor de banco de dados, alguns comandos neste guia podem não funcionar como descrito. Para provisionar um Banco de dados gerenciado pela DigitalOcean siga nossa documentação do produto Bancos de dados gerenciados. Em seguida, você deve instalar o Redli ou configurar um túnel TLS para se conectar ao Banco de dados gerenciado através do TLS.

Como criar conjuntos ordenados e adicionar membros

Para criar um conjunto ordenado, use o comando zadd. O zadd aceita como argumentos o nome da chave que conterá o conjunto ordenado, seguido da pontuação do membro que você está adicionando, e do valor do membro em si. O comando a seguir criará uma chave ordenada chamada faveGuitarists com um membro, "Joe Pass", que tem uma pontuação de 1:

  1. zadd faveGuitarists 1 "Joe Pass"

O zadd retornará um número inteiro que indica a quantidade de membros que foram adicionados ao conjunto ordenado caso tenha sido criado com sucesso.

Output
(integer) 1

É possível adicionar mais de um membro a um conjunto ordenado com o zadd. Note que suas pontuações não precisam ser sequenciais, podem haver lacunas entre as pontuações e vários membros mantidos no mesmo conjunto ordenado podem compartilhar a mesma pontuação:

  1. zadd faveGuitarists 4 "Stephen Malkmus" 2 "Rosetta Tharpe" 3 "Bola Sete" 3 "Doug Martsch" 8 "Elizabeth Cotten" 12 "Nancy Wilson" 4 "Memphis Minnie" 12 "Michael Houser"
Output
(integer) 8

O zadd pode aceitar as seguintes opções, que você deve digitar após o nome de chave e antes da primeira pontuação de membro:

  • NX ou XX: essas opções têm efeitos opostos, de modo que você só pode incluir uma delas em qualquer operação do zadd:
    • NX: diz ao zadd para não atualizar os membros existentes. Com essa opção, o zadd adicionará apenas novos elementos.
    • XX: diz ao zadd para atualizar apenas os elementos existentes. Com essa opção, o zadd nunca adicionará novos membros.
  • CH: normalmente, o zadd retorna apenas o número de novos elementos adicionados ao conjunto ordenado. Com essa opção incluída, no entanto, o zadd retornará o número de elementos alterados. Isso inclui os novos membros e membros cujas pontuações foram alteradas.
  • INCR: isso faz o comando aumentar o valor de pontuação do membro. Caso o membro ainda não exista, o comando o adicionará ao conjunto ordenado com o incremento como sendo sua pontuação, como se sua pontuação inicial fosse 0. Com o INCR incluído, o zadd retornará a nova pontuação do membro caso seja bem-sucedido. Note que você pode incluir apenas um par de pontuação/membro por vez ao usar essa opção.

Ao invés de passar a opção INCR para o zadd, você pode, de forma alternativa, usar o comando do zincrby, que se comporta da mesma maneira. Ao invés de dar ao membro do conjunto ordenado o valor indicado pelo valor de pontuação como o zadd, ele aumentará a pontuação do membro por aquele valor. Por exemplo, o seguinte comando incrementa a pontuação do membro "Stephen Malkmus", que era originalmente 4, em 5 até 9.

  1. zincrby faveGuitarists 5 "Stephen Malkmus"
Output
"9"

Como acontece com a opção INCR do comando zadd, caso o membro especificado não exista, então o zincrby o criará com o valor do incremento como sua pontuação.

Como recuperar os membros de conjuntos ordenados

A maneira mais fundamental de recuperar os membros mantidos dentro de um conjunto ordenado é usar o comando zrange Esse comando aceita como argumentos o nome da chave cujos membros você deseja recuperar e uma faixa de membros mantidos dentro dela. A faixa é definida por dois números que representam indexações baseadas em zero, ou seja, se 0 representa o primeiro membro no conjunto ordenado (ou, o membro com a pontuação mais baixa), 1 representa o seguinte, e assim por diante.

O exemplo a seguir retornará os primeiros quatro membros do conjunto ordenado faveGuitarists, criado na seção anterior:

  1. zrange faveGuitarists 0 3
Output
1) "Joe Pass" 2) "Rosetta Tharpe" 3) "Bola Sete" 4) "Doug Martsch"

Note que, caso o conjunto ordenado que você passa para o zrange tenha dois ou mais elementos que compartilham a mesma pontuação, ele ordenará esses elementos em ordem lexicográfica ou alfabética.

As indexações de início e parada podem também ser números negativos, com -1 representando o último membro, -2 representando o penúltimo, e assim por diante:

  1. zrange faveGuitarists -5 -2
Output
1) "Memphis Minnie" 2) "Elizabeth Cotten" 3) "Stephen Malkmus" 4) "Michael Houser"

O zrange pode aceitar o argumento WITHSCORES que, quando incluído, também retornará as pontuações dos membros:

  1. zrange faveGuitarists 5 6 WITHSCORES
Output
1) "Elizabeth Cotten" 2) "8" 3) "Stephen Malkmus" 4) "9"

O zrange só pode retornar uma faixa de membros em uma ordem numérica ascendente. Para reverter isso e retornar uma faixa em ordem descendente, você deve usar o comando zrevrange. Pense neste comando como sendo uma inversão temporária da ordem do conjunto ordenado, antes de retornar os membros que se situam dentro da faixa especificada. Assim, com o zrevrange, o 0 representará o último membro mantido na chave, 1 representará o penúltimo, e assim por diante:

  1. zrevrange faveGuitarists 0 5
Output
1) "Nancy Wilson" 2) "Michael Houser" 3) "Stephen Malkmus" 4) "Elizabeth Cotten" 5) "Memphis Minnie" 6) "Doug Martsch"

O zrevrange também pode aceitar a opção WITHSCORES.

É possível retornar uma faixa de membros com base nas suas pontuações com o comando zrangebyscore. No exemplo a seguir, o comando retornará todos os membros mantidos na chave faveGuitarists com uma pontuação de 2, 3, ou 4:

  1. zrangebyscore faveGuitarists 2 4
Output
1) "Rosetta Tharpe" 2) "Bola Sete" 3) "Doug Martsch" 4) "Memphis Minnie"

A faixa é inclusiva neste exemplo, o que significa que ela retornará os membros com pontuações de 2 ou 4. É possível excluir qualquer extremidade da faixa, precedendo-a com um parêntese aberto ((). O exemplo a seguir retornará todos os membros com uma pontuação maior ou igual a 2, mas inferior a 4:

  1. zrangebyscore faveGuitarists 2 (4
Output
1) "Rosetta Tharpe" 2) "Bola Sete" 3) "Doug Martsch"

Assim como com o zrange, o zrangebyscore pode aceitar o argumento WITHSCORES. Ele também aceita a opção LIMIT, que você pode usar para recuperar apenas uma seleção de elementos do resultado do zrangebyscore. Essa opção aceita uma referência, que marca o primeiro membro na faixa que o comando retornará e uma contagem, que define a quantidade de membros que o comando retornará no total. Por exemplo, o seguinte comando analisará os primeiros seis membros do conjunto ordenado faveGuitarists, mas retornará apenas três membros a partir dele, começando pelo segundo membro na faixa, representado por 1:

  1. zrangebyscore faveGuitarists 0 5 LIMIT 1 3
Output
1) "Rosetta Tharpe" 2) "Bola Sete" 3) "Doug Martsch"

O comando zrevrangebyscore retorna uma faixa invertida de membros com base nas suas pontuações. O seguinte comando retorna todos os membros do conjunto com uma pontuação entre 10 e 6:

  1. zrevrangebyscore faveGuitarists 10 6
Output
1) "Stephen Malkmus" 2) "Elizabeth Cotten"

Assim como com o zrangebyscore, o zrevrangebyscore pode aceitar as opções WITHSCORES e LIMIT. Além disso, você pode excluir qualquer uma das extremidades da faixa, precedendo-a com um parêntese aberto.

Pode haver situações em que todos os membros em um conjunto ordenado tenham a mesma pontuação. Em tais casos, você pode forçar o redis a retornar uma faixa de elementos ordenados lexicograficamente, ou em ordem alfabética, com o comando do zrangebylex. Para testar este comando, execute o seguinte comando zadd para criar um conjunto ordenado, onde cada membro tenha a mesma pontuação:

  1. zadd SomervilleSquares 0 Davis 0 Inman 0 Union 0 porter 0 magoun 0 ball 0 assembly

O zrangebylex deve ser seguido pelo nome de uma chave, um intervalo de início e um intervalo de parada. Os intervalos de início e parada devem começar com um parêntese aberto (() ou um colchete aberto ([), como isto:

  1. zrangebylex SomervilleSquares [a [z
Output
1) "assembly" 2) "ball" 3) "magoun" 4) "porter"

Note que este exemplo retornou apenas quatro dos oito membros no conjunto, apesar do comando ter procurado uma faixa de a a z. Isso aconteceu porque os valores do Redis são sensíveis ao caso, de modo que os membros que começam em letra maiúscula foram excluídos do resultado. Para retornar, execute o seguinte:

  1. zrangebylex SomervilleSquares [A [z
Output
1) "Davis" 2) "Inman" 3) "Union" 4) "assembly" 5) "ball" 6) "magoun" 7) "porter"

O zrangebylex também aceita o caractere especial - que representam o infinito negativo e o +, que representa o infinito positivo. Assim, a sintaxe de comando a seguir retornará todos os membros do conjunto ordenado:

  1. zrangebylex SomervilleSquares - +

Note que o zrangebylex não pode retornar os membros do conjunto ordenado em uma ordem lexicográfica inversa (alfabética ascendente). Para fazer isso, use o zrevrangebylex:

  1. zrevrangebylex SomervilleSquares + -
Output
1) "porter" 2) "magoun" 3) "ball" 4) "assembly" 5) "Union" 6) "Inman" 7) "Davis"

Como ele é destinado a ser usado com conjuntos ordenados em que cada membro tem a mesma pontuação, o zrangebylex não aceita a opção WITHSCORES. No entanto, ele aceita a opção LIMIT.

Como recuperar informações sobre conjuntos ordenados

Para descobrir a quantidade de membros em um conjunto ordenado determinado (ou, em outras palavras, para determinar sua cardinalidade), use o comando zcard. O exemplo a seguir mostra a quantidade de membros sendo mantidos na chave faveGuitarists, da primeira seção deste guia:

  1. zcard faveGuitarists
Output
(integer) 9

O zcount pode dizer a você a quantidade de elementos sendo mantidos dentro de um determinado conjunto ordenado, que se situam dentro de uma faixa de pontuações. O primeiro número que vem após a chave é o início da faixa e o segundo é o final da faixa:

  1. zcount faveGuitarists 3 8
Output
(integer) 4

O zscore mostra como resultado a pontuação de um membro especificado de um conjunto ordenado:

  1. zscore faveGuitarists "Bola Sete"
Output
"3"

Caso o membro ou a chave especificada não exista, o zscore retornará (nil).

O zrank é semelhante ao zscore, mas, ao invés de retornar a pontuação de um determinado membro, ele retorna a classificação dele. No Redis, a classificação é um índice de base zero dos membros de um conjunto, ordenado pelas pontuações. Por exemplo, "Joe Pass" tem uma pontuação de 1, mas, como essa é a pontuação mais baixa de qualquer membro na chave, ele tem uma classificação de 0:

  1. zrank faveGuitarists "Joe Pass"
Output
(integer) 0

Há outro comando chamado zrevrank que executa a mesma função que o zrank, mas, de maneira contrária, inverte as classificações dos membros no conjunto. No exemplo a seguir, o membro "Joe Pass" tem a pontuação mais baixa, tendo, portanto, a classificação inversa mais elevada:

  1. zrevrank faveGuitarists "Joe Pass"
Output
(integer) 8

A única relação entre a pontuação de um membro e a classificação dele é onde sua pontuação fica em relação à de outros membros. Caso haja uma diferença de pontuação entre dois membros sequenciais, isso não será refletido em sua classificação. Note que, caso dois membros tenham a mesma pontuação, aquele que vem primeiro na ordem alfabética, terá a classificação inferior.

Assim como o zscore, o zrank e zrevrank retornarão (nil) caso a chave ou o membro não exista.

O zlexcount pode dizer a você a quantidade de membros mantida em um conjunto ordenado em uma faixa lexicográfica. O exemplo a seguir utiliza o conjunto ordenado do SomervilleSquares da seção anterior:

  1. zlexcount SomervilleSquares [M [t
Output
(integer) 5

Esse comando segue a mesma sintaxe que o comando zrangebylex, portanto, consulte a seção anterior para mais detalhes sobre como definir uma faixa de strings.

Como remover os membros de conjuntos ordenados

O comando zrem pode remover um ou mais membros de um conjunto ordenado:

  1. zrem faveGuitarists "Doug Martsch" "Bola Sete"

O zrem retornará um número inteiro, indicando a quantidade de membros removidos do conjunto ordenado:

Output
(integer) 2

Há três comandos do Redis que permitem que você remova os membros de um conjunto ordenado com base em uma faixa. Por exemplo, caso cada membro em um conjunto ordenado tenha a mesma pontuação, remova os membros com base em uma faixa lexicográfica com o zremrangebylex. Esse comando utiliza a mesma sintaxe que o zrangebylex. O exemplo a seguir removerá todos os membros que começam com uma letra maiúscula da chave SomervilleSquares criada na seção anterior:

  1. zremrangebylex SomervilleSquares [A [Z

O zremrangebylex dará como resultado um número inteiro, indicando a quantidade de membros que ele removeu:

Output
(integer) 3

Você também pode remover os membros com base em uma faixa de pontuações com o comando zremrangebyscore, que utiliza a mesma sintaxe que o comando zrangebyscore. O exemplo a seguir removerá todos os membros mantidos em faveGuitarists com uma pontuação de 4, 5, ou 6:

  1. zremrangebyscore faveGuitarists 4 6
Output
(integer) 1

Você pode remover os membros de um conjunto com base em uma faixa de classificações com o comando zremrangebyrank, que utiliza a mesma sintaxe que o zrangebyrank. O comando a seguir removerá os três membros do conjunto ordenado com as classificações mais baixas, que são definidas por uma faixa de indexações com base zero:

  1. zremrangebyrank faveGuitarists 0 2
Output
(integer) 3

Note que os números passados para o remrangebyrank também podem ser negativos, com -1 representando a classificação mais alta, -2 a segunda mais alta e assim por diante.

Como criar novos conjuntos ordenados a partir de outros existentes

O Redis inclui dois comandos que permitem que você compare os membros de vários conjuntos ordenados e crie novos com base nessas comparações: o zinterstore e o zunionstore. Para testar esses comandos, execute os comandos zadd a seguir para criar alguns exemplos de conjuntos ordenados.

  1. zadd NewKids 1 "Jonathan" 2 "Jordan" 3 "Joey" 4 "Donnie" 5 "Danny"
  2. zadd Nsync 1 "Justin" 2 "Chris" 3 "Joey" 4 "Lance" 5 "JC"

O zinterstore encontra os membros compartilhados por dois ou mais conjuntos ordenados — sua intersecção — e produz um novo conjunto ordenado que contenha apenas esses membros. Esse comando deve incluir, em ordem, o nome de uma chave de destino onde os membros da intersecção serão armazenados como um conjunto ordenado, o número de chaves sendo passadas para o zinterstore e os nomes das chaves que você quer analisar:

  1. zinterstore BoyBands 2 NewKids Nsync

O zinterstore retornará um número inteiro que mostra o número de elementos armazenados no conjunto ordenado de destino. Como NewKids e Nsync compartilham apenas um membro, "Joey", o comando retornará 1:

Output
(integer) 1

Esteja ciente de que, caso a chave de destino já exista, o zinterstore irá sobrescrever o conteúdo dela.

O zunionstore criará um novo conjunto ordenado que possui todos os membros das chaves passadas a ele. Este comando utiliza a mesma sintaxe que o zinterstore e exige o nome de uma chave de destino, o número de chaves sendo passadas para o comando e os nomes das chaves:

  1. zunionstore SuperGroup 2 NewKids Nsync

Assim como o zinterstore, o zunionstore retornará um número inteiro, mostrando o número de elementos armazenados na chave de destino. Embora ambos os conjuntos ordenados originais tivessem cinco membros, como os conjuntos ordenados não podem ter membros repetidos e cada chave tem um membro chamado "Joey", o número inteiro resultante será 9:

Output
(integer) 9

Assim como o zinterstore, o zunionstore irá sobrepor o conteúdo da chave de destino, caso já exista.

Para dar mais controle sobre as pontuações dos membros ao criar novos conjuntos ordenados com o zinterstore e zunionstore, ambos esses comandos aceitam as opções WEIGHTS e AGGREGATE.

A opção WEIGHTS vem seguida de um número para cada conjunto ordenado incluído no comando que pesa, ou multiplica, as pontuações de cada membro. O primeiro número após a opção WEIGHTS pesa as pontuações da primeira chave enviadas para o comando, o segundo número pesa a segunda chave, e assim por diante.

O exemplo a seguir cria um conjunto ordenado novo, que possui as chaves em intersecção dos conjuntos ordenados NewKids e Nsync. Ele pesa as pontuações na chave NewKids por um fator de três e pesa as que estão na chave Nsync por um fator de sete:

  1. zinterstore BoyBandsWeighted 2 NewKids Nsync WEIGHTS 3 7

Caso a opção WEIGHTS não seja incluída, a pesagem assume o padrão 1 para o zinterstore e o zunionstore.

O AGGREGATE aceita três subopções. O primeiro deles, SUM, implementa o comportamento padrão do zinterstore e do zunionstore, adicionando as pontuações de membros correspondentes nos conjuntos combinados.

Caso execute uma operação zinterstore ou zunionstore em dois conjuntos ordenados que partilham um membro, mas este membro tem uma pontuação diferente em cada conjunto, você pode forçar a operação a atribuir a menor das duas pontuações no novo conjunto com a subopção MIN.

  1. zinterstore BoyBandsWeightedMin 2 NewKids Nsync WEIGHTS 3 7 AGGREGATE MIN

Como os dois conjuntos ordenados têm apenas um membro correspondente com a mesma pontuação (3), este comando criará um novo conjunto com um membro que tem o menor das duas pontuações ponderadas:

  1. zscore BoyBandsWeightedMin "Joey"
Output
"9"

De maneira similar, o AGGREGATE pode forçar o zinterstore ou zunionstore a atribuir a maior das duas pontuações com a opção MAX:

  1. zinterstore BoyBandsWeightedMax 2 NewKids Nsync WEIGHTS 3 7 AGGREGATE MAX

Esse comando cria um novo conjunto com um membro, "Joey", que tem a mais alto das duas pontuações ponderadas:

  1. zscore BoyBandsWeightedMax "Joey"
Output
"21"

É útil pensar em WEIGHTS como uma maneira de manipular temporariamente as pontuações dos membros antes de serem analisadas. De maneira similar, é útil pensar na opção AGGREGATE como uma forma de decidir como controlar as pontuações dos membros antes de serem adicionadas aos seus novos conjuntos.

Conclusão

Esse guia detalha vários comandos usados para criar e gerenciar conjuntos ordenados no Redis. Caso haja outros comandos, argumentos ou procedimentos relacionados que você gostaria de ver apresentados neste guia, faça perguntas ou sugestões nos comentários abaixo.

Para obter mais informações sobre os comandos do Redis, consulte nossa série de tutoriais sobre Como gerenciar um banco de dados Redis.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about us


About the authors
Default avatar

Manager, Developer Education

Technical Writer @ DigitalOcean

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
Leave a comment


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Get our biweekly newsletter

Sign up for Infrastructure as a Newsletter.

Hollie's Hub for Good

Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

Become a contributor

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

Welcome to the developer cloud

DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

Learn more
DigitalOcean Cloud Control Panel