Redis, Jedis et les Sets

Je continue ma dĂ©couverte de Redis et Jedis (suite de l’article http://k33g.github.io/2014/05/22/PLAYING-WITH-REDIS.html sur Redis et les HashMaps). J’avais alors dĂ©couvert la commande keys(matchParameters) que je trouvais assez gĂ©niale, mais l’on m’a fait remarquer Ă  juste titre que ce n’était pas performant et qu’il valait mieux utiliser des sets pour classer ses donnĂ©es selon certains critĂšres.

Le sets, voyez ça comme un “couple” clĂ©, liste de valeurs oĂč les valeurs sont des strings.

Connexion Ă  Redis et dĂ©finition des “humains”

Ça c’est la mĂȘme chose que la derniĂšre fois (avec une fille en plus)

Jedis jedis = new Jedis("localhost", 6379);

HashMap<String, String> bob = new HashMap<String, String>() {{
  put("firstName", "Bob");
  put("lastName", "Morane");
}};

HashMap<String, String> john = new HashMap<String, String>() {{
  put("firstName", "John");
  put("lastName", "Doe");
}};

HashMap<String, String> jane = new HashMap<String, String>() {{
  put("firstName", "Jane");
  put("lastName", "Doe");
}};

HashMap<String, String> wonderWoman = new HashMap<String, String>() {{
  put("firstName", "Lynda");
  put("lastName", "Carter");
}};

Et je sauvegarde en base mes hashmaps:

jedis.hmset("bob", bob);
jedis.hmset("john", john);
jedis.hmset("jane", jane);
jedis.hmset("lynda", wonderWoman);

Classer mes données avec des sets

Je vais crĂ©er 3 sets : "females", "males", "humans" pour “classer” mes hasmaps, grĂące Ă  la commande sadd Ă  laquelle je passe une clĂ© unique pour identifier le set et une liste de valeurs sous forme de string (qui ici reprĂ©sentent les clĂ©s de mes hashs):

jedis.sadd("females", "jane", "lynda");
jedis.sadd("males","bob", "john"); 
jedis.sadd("humans", "bob", "jane", "lynda", "john");

Interroger mes sets

Maintenant si je souhaite avoir toutes les "females", il me suffit d’écrire ceci en utilisant la commande smembers et en lui passant la clĂ© du set que je veux parcourir:

jedis.smembers("females").forEach((key) -> System.out.println(jedis.hgetAll(key)));

Et nous obtiendrons:

{lastName=Carter, firstName=Lynda}
{lastName=Doe, firstName=Jane}

Si je veux compter le nombre de "males", j’utiliserais la commande scard

System.out.println(jedis.scard("males")); // nous obtiendrons 2

Suppressions

Si je supprime la “hash” Lynda:

jedis.del("lynda");

Et que je relance le parcours du set "females":

jedis.smembers("females").forEach((key) -> System.out.println(jedis.hgetAll(key)));

Et nous obtiendrons:

{}
{lastName=Doe, firstName=Jane}

Notez bien que la suppression de la “hash” ne supprime pas l’enregistrement dans le set, ce qui est logique, mais tout le monde peut se tromper.

Pour supprimer un enregistrement du set, il suffit d’utiliser la commande srem en lui passant la clĂ© du set et la valeur Ă  supprimer:

jedis.srem("females","lynda");

Scan

On peut parcourir un set avec des critĂšres de recherche avec la mĂ©thode sscan qui permet de parcourir les valeur d’un set et d’en extraire celles qui correspondent Ă  au critĂšre. Le critĂšre fonctionne de la mĂȘme façon qu’avec keys : par exemple, je veux toutes les valeurs qui contiennent le caractĂšre "a", alors mon critĂšre sera : *a*. On retombe dans une problĂ©matique de performance, mais on aura beaucoup moins de clĂ©s Ă  parcourir par rapport Ă  avant oĂč l’on scannait la base entiĂšre.

Donc, imaginons que je veuille tous les "humans" dont la clĂ© contient "a", j’écrirais ceci:

Je définis mon paramÚtre de recherche:

ScanParams params = new ScanParams();
params.match("*a*");

J’interroge mon set

jedis.sscan("humans", SCAN_POINTER_START , params)
      .getResult()
      .forEach((key) -> System.out.println("key " + key + " : " + jedis.hgetAll(key)));

J’obtiendrais:

key jane : {lastName=Doe, firstName=Jane}
key lynda : {lastName=Carter, firstName=Lynda}

Remarque: SCAN_POINTER_START (ou redis.clients.jedis.ScanParams.SCAN_POINTER_START) correspond Ă  String.valueOf(0) : je scanne Ă  partir du 1er enregistrement.

Remarque bis: Ă  manier avec prĂ©caution et parcimonie http://redis.io/commands/scan, je cite “It is important to note that the MATCH filter is applied after elements are retrieved from the collection, just before returning data to the client.”

Voilà, j’avance tout doucement, la prochaine fois je travaillerais sur les range (je pense).

blog comments powered by Disqus

Related posts