{"id":12549,"date":"2017-07-05T19:09:42","date_gmt":"2017-07-05T17:09:42","guid":{"rendered":"http:\/\/www.devapp.it\/wordpress\/?p=12549"},"modified":"2017-07-05T19:09:42","modified_gmt":"2017-07-05T17:09:42","slug":"redis-iniziamo-ad-usarlo-con-node-js","status":"publish","type":"post","link":"https:\/\/www.devapp.it\/wordpress\/redis-iniziamo-ad-usarlo-con-node-js\/","title":{"rendered":"Redis: iniziamo ad usarlo con Node.js"},"content":{"rendered":"<p>In questo articolo, introdurremo\u00a0un DBMS divenuto una realt\u00e0 molto importante del mondo NoSQL,\u00a0<a href=\"http:\/\/redis.io\/\">Redis<\/a>, e vedremo come sia agevole la sua integrazione\u00a0in un&#8217;app <a href=\"http:\/\/www.devapp.it\/wordpress\/introduzione-a-node-js\/\" target=\"_blank\" rel=\"noopener\">Node.js<\/a>. Redis appartiene alla tipologia <strong>key\/value:\u00a0<\/strong>l&#8217;intero database, in pratica, \u00e8\u00a0una struttura a &#8220;dizionario&#8221; dove si immagazzinano valori associati ad una chiave univoca che ne permetter\u00e0 un immediato recupero. Uno degli aspetti pi\u00f9 importanti di\u00a0Redis consiste nella sua capacit\u00e0 di immagazzinare come valori non solo semplici stringhe ma intere\u00a0strutture dati tipo\u00a0HashMap (strutture a dizionario esse stesse), liste, insiemi. Vediamo da vicino come funziona.<\/p>\n<h2>Iniziamo con\u00a0Redis<\/h2>\n<p>Per prima cosa, scarichiamo ed installiamo Redis. Dalla pagina dei <a href=\"http:\/\/redis.io\/download\">Downloads<\/a>, otteniamo\u00a0il pacchetto di sorgenti\u00a0nella versione che desideriamo e, seguendo le istruzioni, lo decomprimiamo e compiliamo i sorgenti tramite il comando <em>make<\/em>.<\/p>\n<p>Fatto ci\u00f2, nella cartella <em>src<\/em>\u00a0troveremo il comando <em>redis-server<\/em> con cui attiveremo subito il server e <em>redis-cli<\/em> con cui interagiremo da riga di comando.<\/p>\n<p>Una volta avviata la console <em>redis-cli<\/em>, potremo\u00a0passare al server comandi \u00a0la cui documentazione completa risiede in un&#8217;utile <a href=\"http:\/\/redis.io\/commands\">pagina<\/a> riepilogativa presente sul sito ufficiale.<\/p>\n<p>Di default, Redis possiede 16 database e dalla console, all&#8217;ingresso, si inizia\u00a0ad interagire con il database numero 0 con la possibilit\u00e0 di cambiarlo\u00a0all&#8217;occorrenza tramite il comando <a href=\"https:\/\/redis.io\/commands\/select\" target=\"_blank\" rel=\"noopener\">SELECT<\/a>: ad esempio, digitando <code>SELECT 1<\/code>, inizieremo ad utilizzare il database numero 1.<\/p>\n<p>Esistono molti altri <a href=\"https:\/\/redis.io\/commands#server\" target=\"_blank\" rel=\"noopener\">comandi che agiscono sul server<\/a> o sui singoli database e qui di seguito ne indichiamo alcuni che possono essere particolarmente utili nei primi approcci con Redis:<\/p>\n<ul>\n<li><a href=\"https:\/\/redis.io\/commands\/info\" target=\"_blank\" rel=\"noopener\">INFO<\/a>: informazioni complessive su tutti gli aspetti del server;<\/li>\n<li><a href=\"https:\/\/redis.io\/commands\/dbsize\" target=\"_blank\" rel=\"noopener\">DBSIZE<\/a>: fornisce il numero di chiavi registrate attualmente nel database corrente;<\/li>\n<li><a href=\"https:\/\/redis.io\/commands\/flushdb\" target=\"_blank\" rel=\"noopener\">FLUSHDB<\/a>: elimina tutti gli elementi registrati nel database corrente.<\/li>\n<\/ul>\n<p>Quanto detto pu\u00f2 essere utile per prendere confidenza con questo DBMS ma ora \u00e8 il momento di iniziare ad inserirvi dei valori.<\/p>\n<h2>Primi dati in Redis<\/h2>\n<p>Dopo aver aperto la console di Redis, possiamo iniziare a\u00a0vedere i casi pi\u00f9 comuni di gestione dati:<\/p>\n<ul>\n<li>gestione di stringhe:\n<pre class=\"lang:sh decode:true\">127.0.0.1:6379&gt; set nome Paolo\r\nOK\r\n127.0.0.1:6379&gt; get nome\r\n\"Paolo\"\r\n127.0.0.1:6379&gt;\r\n<\/pre>\n<\/li>\n<li>gestione di hashmap:\n<pre class=\"lang:sh decode:true \">127.0.0.1:6379&gt; HMSET  pagella 'Italiano' 8 'Storia' 9 'Matematica' 6\r\nOK\r\n127.0.0.1:6379&gt; HGET pagella Matematica\r\n\"6\"\r\n127.0.0.1:6379&gt; HGETALL pagella\r\n1) \"Italiano\"\r\n2) \"8\"\r\n3) \"Storia\"\r\n4) \"9\"\r\n5) \"Matematica\"\r\n6) \"6\"\r\n<\/pre>\n<p>in questo modo creiamo una struttura dati a dizionario con chiave &#8216;pagella&#8217; il cui valore contiene i nomi delle materie, come chiave, ed il voto conseguito come valore. Notare come vengono memorizzati i dati: in pratica, sembrano elencati come in una lista ma svolgono, alternatamente, il ruolo di chiave o di valore;<\/li>\n<li>ed infine vediamo le liste:\n<pre class=\"lang:sh decode:true\">127.0.0.1:6379&gt; RPUSH animali cane gatto topo mucca coniglio cavallo\r\n(integer) 6\r\n127.0.0.1:6379&gt; LRANGE animali 0 2\r\n1) \"cane\"\r\n2) \"gatto\"\r\n3) \"topo\"\r\n127.0.0.1:6379&gt; LRANGE animali 0 -1\r\n1) \"cane\"\r\n2) \"gatto\"\r\n3) \"topo\"\r\n4) \"mucca\"\r\n5) \"coniglio\"\r\n6) \"cavallo\"\r\n<\/pre>\n<p>con le interazioni precedenti abbiamo creato una lista di sei elementi (tutte stringhe contenenti nomi di animali) e ne abbiamo estratto un subset. Il comando <a href=\"https:\/\/redis.io\/commands\/rpush\" target=\"_blank\" rel=\"noopener\">RPUSH<\/a> inserisce valori in coda alla lista mentre <a href=\"https:\/\/redis.io\/commands\/lpush\" target=\"_blank\" rel=\"noopener\">LPUSH<\/a> li avrebbe inseriti in testa.<\/li>\n<\/ul>\n<p>Dopo aver effettuato questi ed altri esperimenti traendo spunto dalla documentazione ufficiale, si ricordi che si pu\u00f2 vedere l&#8217;elenco di tutte le chiavi inserite tramite il comando <a href=\"https:\/\/redis.io\/commands\/KEYS\" target=\"_blank\" rel=\"noopener\">KEYS<\/a>, nella forma:<\/p>\n<pre class=\"lang:sh decode:true\">127.0.0.1:6379&gt; KEYS *<\/pre>\n<h2>Programmiamo con Redis in Node.js<\/h2>\n<p>Si potrebbe continuare a lungo a suggerire comandi da sperimentare sulla cli di Redis ma preferiamo passare ad un impiego legato gi\u00e0 alla programmazione con Node.js. Creeremo del codice (scaricabile a <a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2016\/11\/node-redis.zip\" target=\"_blank\" rel=\"noopener\">questo link<\/a>)\u00a0che in poche righe ci permetter\u00e0 di scaricare\u00a0dati finanziari dal sito <a href=\"https:\/\/it.finance.yahoo.com\/\" target=\"_blank\" rel=\"noopener\">Yahoo! Finanza<\/a>\u00a0ed immagazzinarli in Redis. Il portale in questione permette di scaricare la quotazione attuale di un titolo azionario (ritardato di alcuni minuti) inviando una richiesta HTTP ad un indirizzo nel formato\u00a0<em>http:\/\/download.finance.yahoo.com\/d\/quotes.csv?s=<strong>CODICE<\/strong>&amp;f=sl1d1t1c1ohgv&amp;e=.csv<\/em> dove, al posto della stringa CODICE, passeremo un identificativo che distingue, nei mercati azionari, il titolo che siamo interessati a monitorare.<\/p>\n<p>Ad esempio, cercando il titolo relativo all&#8217;azienda Mediaset S.p.A. su Yahoo Finanza raggiungeremo la sua <a href=\"https:\/\/it.finance.yahoo.com\/q?s=MS.MI\" target=\"_blank\" rel=\"noopener\">pagina<\/a>\u00a0(codice MS.MI)\u00a0e scorrendola verso il basso, sulla destra, scorgeremo il link che permette di scaricare i dati:<\/p>\n<p><a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2016\/11\/redis_nodejs_database_nosql_01.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-12609\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2016\/11\/redis_nodejs_database_nosql_01-300x133.jpg\" alt=\"redis_nodejs_database_nosql_01\" width=\"300\" height=\"133\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2016\/11\/redis_nodejs_database_nosql_01-300x133.jpg 300w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2016\/11\/redis_nodejs_database_nosql_01.jpg 385w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>Ai fini del nostro esercizio, tramite i comandi offerti dal browser, potremo leggere a quale indirizzo HTTP il link\u00a0punti realmente e avremo conferma che segue proprio il formato che abbiamo descritto poco fa. Questi i dati ottenuti:<\/p>\n<pre class=\"lang:sh decode:true \">\"MS.MI\",2.28,\"11\/18\/2016\",\"5:41pm\",-0.06,2.33,2.36,2.28,8057185<\/pre>\n<p>Una volta ottenuti, li interpreteremo\u00a0nell&#8217;app Node.js\u00a0prendendo\u00a0il primo &#8211; il codice del titolo &#8211;\u00a0pulendolo\u00a0dai doppi apici ed il secondo che rappresenta il prezzo in euro equivalente. Fatto ci\u00f2, inseriremo il tutto <strong>in Redis usando il codice del titolo per formare la\u00a0chiave ed il suo prezzo attuale come valore<\/strong>: questo ci consentir\u00e0 di avere le quotazioni aggiornate continuamente nel nostro database.<\/p>\n<p>In Node.js, faremo uso di due estensioni: <a href=\"https:\/\/github.com\/NodeRedis\/node_redis\">node_redis<\/a> per l&#8217;interazione con il database e <a href=\"https:\/\/github.com\/request\/request\">request<\/a> per un comodo scaricamento di \u00a0dati da Internet.\u00a0La loro installazione\u00a0con <em>npm<\/em> segue le consuete modalit\u00e0:<\/p>\n<pre class=\"lang:sh decode:true \">&gt; npm init\r\n&gt; npm install request redis --install\r\n&gt; npm install request request --install<\/pre>\n<p>Questa la nostra app:<\/p>\n<pre class=\"lang:js decode:true \">\/\/ inclusione moduli necessari\r\nvar redis = require('redis');\r\nvar request=require('request');\r\n\r\n\/\/ definizione di un client Redis\r\nvar client = redis.createClient();\r\n\r\n\/\/ gestione degli errori in Redis\r\nclient.on('error', function (err) {\r\n console.log(\"Errore: Redis ha risposto \"+err);\r\n});\r\n\r\nfunction nomeAzione(s)\r\n{\r\n \/\/ eliminiamo tutti gli apici dalla stringa\r\n return s.replace(\/\"\/g,'');\r\n}\r\n\r\nfunction creaIndirizzo(codice)\r\n{\r\n \/\/ inseriamo il codice del titolo azionario nell'indirizzo\r\n return 'http:\/\/download.finance.yahoo.com\/d\/quotes.csv?s='+codice+'&amp;f=sl1d1t1c1ohgv&amp;e=.csv';\r\n}\r\n\r\nfunction scaricaDati(codice)\r\n{\r\n \/\/ scaricamento dati dal sito\r\n request(creaIndirizzo(codice), \r\n function (error, response, body) {\r\n if (!error &amp;&amp; response.statusCode == 200) {\r\n \/\/ codice di risposta HTTP 200: tutto ok!\r\n\r\n \/\/ costruiamo array con le parti della stringa separate da virgola\r\n ar=body.split(',');\r\n\r\n if (ar.length&gt;1)\r\n {\r\n \/* se l'array ha almeno due elementi assumiamo che il primo sia il nome del titolo \r\n ed il secondo il suo valore: si possono effettuare ulteriori controlli sul formato *\/\r\n nome=nomeAzione(ar[0]);\r\n valore=ar[1];\r\n\r\n \/\/ inseriamo in Redis la coppia nome titolo\/valore\r\n \/\/ N.B.: applichiamo il prefisso \"stock:\" per riconoscere queste chiavi nel db\r\n client.set(\"stock:\"+nome,valore, redis.print);\r\n\r\n } \r\n }\r\n });\r\n}\r\n\r\n\/* codici relativi ai titoli di nostro interesse:\r\n Telecom Italia, Intesa San Paolo, ENI, Enel, Mediaset *\/\r\nvar daScaricare=['TIT.MI','ISP.MI','ENI.MI','ENEL.MI','MS.MI'];\r\n\r\n\/\/ avvio del ciclo: scarichiamo i dati\r\ndaScaricare.forEach(function(v,i,a)\r\n{\r\n scaricaDati(v);\r\n});<\/pre>\n<p>Un aspetto importante da notare \u00e8 che utilizziamo come chiave per le strutture dati il codice del titolo anteponendo per\u00f2\u00a0il\u00a0prefisso &#8220;stock:&#8221;: ci\u00f2 al fine di poterlo riconoscere nel set di chiavi registrate nel database.<\/p>\n<p>Il risultato sar\u00e0 disponibile in Redis e potremo\u00a0averne rapidamente dimostrazione tramite i seguenti comandi\u00a0da client testuale:<\/p>\n<pre class=\"lang:sh decode:true\">127.0.0.1:6379&gt; keys stock*\r\n1) \"stock:MS.MI\"\r\n2) \"stock:ENEL.MI\"\r\n3) \"stock:ENI.MI\"\r\n4) \"stock:TIT.MI\"\r\n5) \"stock:ISP.MI\"\r\n127.0.0.1:6379&gt; GET stock:ENEL.MI\r\n\"3.73\"\r\n<\/pre>\n<p>Il codice dell&#8217;app \u00e8 piuttosto breve consistendo solo nell&#8217;immagazzinamento di dati scaricati all&#8217;interno del database eppure ha il vantaggio di mostrare gli elementi salienti dell&#8217;interazione Node.js\/Redis. Riassumiamoli:<\/p>\n<ul>\n<li>con il metodo <em>createClient<\/em> dell&#8217;oggetto <em>redis<\/em> stabiliamo la connessione che di default viene effettuata verso l&#8217;indirizzo localhost sulla porta TCP 6379 ma se si ha bisogno di specificare coordinate di rete differenti le si pu\u00f2 passare come argomenti del metodo;<\/li>\n<li>in un normale array Javascript, di nome <em>daScaricare<\/em>, inseriamo i codici dei titoli che vogliamo monitorare e, subito dopo, con un ciclo <em>forEach<\/em> passiamo ognuno di essi al metodo <em>scaricaDati<\/em> che \u00e8 il cuore dell&#8217;esperimento in quanto raccoglie sia l&#8217;interazione in rete che verso il database\u00a0Redis;<\/li>\n<li>l&#8217;oggetto <em>request<\/em> ci permette di svolgere velocemente una lettura attraverso la rete richiedendo un URL da contattare ed un listener cui inviare il risultato.<\/li>\n<\/ul>\n<h2>Conclusioni<\/h2>\n<p>L&#8217;esempio pu\u00f2 essere esteso con facilit\u00e0. Ad esempio, si potrebbe creare delle API REST sfruttando Express e quanto appreso nei <a href=\"http:\/\/www.devapp.it\/wordpress\/creare-api-rest-con-node-js-ed-express-js\/\" target=\"_blank\" rel=\"noopener\">nostri tutorial precedenti<\/a>. L&#8217;occasione comunque non mancher\u00e0 visto che le potenzialit\u00e0 sono ancora notevoli ed il nostro discorso \u00e8 appena iniziato: ben presto vedremo un utilizzo pi\u00f9 articolato\u00a0di queste due tecnologie insieme.<\/p>\n<p>Alla prossima!<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In questo articolo, introdurremo\u00a0un DBMS divenuto una realt\u00e0 molto importante del mondo NoSQL,\u00a0Redis, e vedremo come sia&#8230;<\/p>\n","protected":false},"author":561,"featured_media":13154,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[30,1],"tags":[1530,1543,1537,1791],"class_list":["post-12549","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-materiale-open-source","category-tutorial-pratici","tag-database","tag-database-nosql","tag-node-js","tag-redis"],"acf":[],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/12549","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/users\/561"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/comments?post=12549"}],"version-history":[{"count":11,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/12549\/revisions"}],"predecessor-version":[{"id":13155,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/12549\/revisions\/13155"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/media\/13154"}],"wp:attachment":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/media?parent=12549"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/categories?post=12549"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/tags?post=12549"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}