Redis : Filtrer et trier vos données comme en SQL avec SORT

Redis : Comment filtrer et trier vos données comme avec SQL

Redis est une base de données qui stocke vos données en mémoire et qui est le plus souvent utilisé pour faire du cache et parfois aussi comme message broker.

La plupart du temps, il est donc utilisé comme simple cache clé/valeur mais il fourni également des structures permettant de stocker par exemple des listes de données (sets), des clés-valeurs (hashes / hash sets), des sets ordonnés (sorted sets) et bien d'autres.

Dans cet article, nous allons principalement nous intéresser aux types Set et HSet afin de voir de quelle façon il nous serait possible de filtrer et trier ces données, comme on le ferait avec du SQL.

Ce n'est certainement pas une bonne pratique, vous aurez dans la plupart des cas à utiliser une base de données relationnelle mais il peut s'avérer utile de connaitre ces mécanismes dans certains cas.

Type : Sets

Les Sets Redis permettent d'insérer sous une clé donnée, un ensemble de valeur. Prennoms, par exemple, le cas d'une liste de produits, il nous est possible de stocker dans Redis le Set suivant :

products
product:id:1
product:id:2
product:id:3
...

Les commandes Redis permettant d'insérer, modifier et lister les éléments d'un set sont, entre autre : SADD, SREM et SMEMBERS.

Donc pour insérer nos données dans le set set:products :

> SADD set:products product:id:1 product:id:2 product:id:3
(integer) 1

> SREM set:product:id:2
(integer) 1

> SMEMBERS set:products
1) "product:id:1"
2) "product:id:3"

Il nous est alors facilement possible de créer des sets contenant uniquement les identifiants des données qui doivent être à l'intérieur de ce set, pour classifier les produits en fonction d'une catégorie, par exemple.

Dans le cas ou les produits dont les identifiants sont 1 et 2 seraient associés à une catégorie electronic, je peux les ajouter dans un set dédié, qui me sera utile plus tard :

> SADD set:products:category:electronic product:id:1 product:id:2
(integer) 1

Jusqu'ici, rien de très compliqué. Allons maintenant un peu plus loin avec les HSets.

Type : HSets (Hashes)

Les HSet permettent de stocker plusieurs champs/valeur dans une même clé. On commence donc à entre-voir une relation avec les colonne/valeur d'une base de données relationnelle.

Les commandes Redis permettent d'insérer/modifier et lister les champs d'un hset sont, entre autre : HSET, HGET et HGETALL.

Faisons donc évoluer notre table produit avec de nouveaux champs : price et created_at.

Côté Redis, nous aurions donc les clés avec les couples champ/valeur suivants :

key price created_at
hset:product:id:1 9.99 2021-01-17T14:00:00Z
hset:product:id:2 29.99 2021-01-17T15:00:02Z
hset:product:id:3 49.99 2021-01-17T16:00:04Z
... ... ...

Note : Contrairement à un set classique, nous avons bien ici 3 HSets distincts pour chaque clé. Par soucis de nomenclature et pour pouvoir accéder aux clés rapidement, je les préfixe toujours par hset:.

Pour créer ces entrées dans Redis :

> HSET hset:product:id:1 price 9.99 created_at 2021-01-17T14:00:00Z
(integer) 1
> HSET hset:product:id:2 price 29.99 created_at 2021-01-17T15:00:00Z
(integer) 1
> HSET hset:product:id:3 price 29.99 created_at 2021-01-17T16:00:00Z
(integer) 1

Maintenant, pour obtenir le champ price du produit avec l'identifiant 2 :

> HGET hset:product:id:2 price
"29.99"

Pour récupérer tous les champs, il suffit d'utiliser HGETALL :

> HGETALL hset:product:id:2
"price"
"29.99"
"created_at"
"2021-01-17T15:00:00Z"

Bien, nous avons maintenant tous les éléments pour nous permettre de requêter nos données de façon très similaire à ce que nous connaissons avec SQL. Pour cela, nous allons utiliser la commande SORT, qui, contrairement à ce que son nom indique, permet de faire bien plus qu'un simple trie.

Requêter les données avec SORT

Je vous invite à vous rendre sur la page de la documentation officielle de la commande SORT.

Cette commande permet de réaliser en premier lieu le trie d'un set par ordre alphanumérique ascendant/descendant mais aussi de trier les données en fonction d'une colonne fournie dans un HSet.

On peut également lui donner directement le nom du set correspondant à notre filtre (catégorie electronic par exemple). Imaginons alors la requête SQL suivante :

> SELECT price
  FROM products
  WHERE category = 'electronic'
  ORDER BY created_at DESC

Cette requête nous permet d'obtenir le prix des produits de la catégorie "electronic", ordonnés par date de création descendante.

Avec la fonction SORT de Redis, pour faire cette même requête, il suffit de faire :

> SORT set:products:category:electronic
  BY hset:products:id:*->created_at
  GET hset:products:id:*->price
  DESC

"29.99"
"9.99"

Ici, le pattern * sera remplacé par chaque valeur fournie dans le Set set:products:category:electronic, dans notre cas l'identifiant du produit.

Dans le cas ou vous auriez également des clé/valeurs simples sous la forme product:id:1 avec des données sérializées dans un format particulier, il vous est également possible de les récupérer en passant dans la méthode SORT le pattern GET product:id:*.

Comment faire des filtres multiples ?

La requête SQL reste assez simple dans ce cas mais il est possible d'aller plus loin en faisant des intersections ou des union entre plusieurs stores. Celles-ci peuvent être réalisées via les commandes SINTERSTORE et SUNIONSTORE.

Ainsi, le cas ou vous auriez deux sets : set:products:category:electronic et set:products:category:computer et que des produits soient en commun dans ces deux stores, vous pouvez créer un Set contenant les éléments en commun dans les deux stores avec :

> SINTERSTORE set:products:category:electronic-and-computer set:products:category:electronic set:products:category:computer
(integer) 1

Vous pouvez ensuite utiliser ce set comme un set classique. Il est également possible de générer ce set à la volée (sans le stocker dans Redis) avec SINTER ou SUNION.

Conclusion

Redis reste un très bon outil pour faire du cache distribué, n'est certainement par voué à devenir votre base de données principale, mais dans certains cas, il peut s'avérer utile de connaitre ces manipulations afin de vous permettre de mieux exploiter vos données.

J'espère que cet article vous aura été utile, n'hésitez pas à me contacter pour toute information complémentaire.