A time series is an ordered sequence of values that are made over a time interval. You can use time series in statistics, communications, and social networks.  I this tutorial we are going to create a simple stock time series Node.js library using Redis Strings. This library records events per second, minute, hour, and day.
This library will be able to save an event at a given timestamp with an insert method and fetch values within a range of timestamps with a fetch method. The library we are going to create provides multiple granularities: second, minute, hour, and day. For example, if an event happens on date 8/11/2015 at 00:00:00(timestamp 1446940800), the following Redis keys will be incremented:
– event:1sec:1446940800
– event:1min:1446940800
– event:1hour:1446940800
– event:1day:1446940800
Create a file stock-timeseries.js with the following code:
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91  | 
						//time series constructor. Requires a redis client and a namespace function TimeSeries(client, namespace){     this.namespace = namespace;     this.client = client;     //granularity names and their equivalents in seconds     this.units = {         second:1,         minute: 60,         hour: 60 * 60,         day: 24 * 60 * 60     };     //each granularity has a name, TTL(time to live) and a duration.     //the null ttl present on 1dat meands that this ttl never expires     this.granularities = {         '1sec': {name: '1sec', ttl: this.units.hour * 2, duration: this.units.second},         '1min': {name: '1min', ttl: this.units.day * 7, duration: this.units.minute},         '1hour': {name: '1hour', ttl: this.units.day * 60, duration: this.units.hour},         '1day': {name: '1day', ttl: null, duration: this.units.day}     }; } //insert a particular price at a given timestamp TimeSeries.prototype.insert = function(timestampInSeconds, price){     //iterate over all franularities     for (var granularityName in this.granularities){         var granularity = this.granularities[granularityName];         //get a key name in the format "napespace:granularity:timestamp"         //for ex.: "google:1sec:12"         var key = this._getKeyName(granularity, timestampInSeconds);         //execute the SET command         this.client.set(key, price);         //the EXPIRE command         //pass the key and the ttl         //this command deletes a redis key automatically after a given number         //of seconds         if(granularity.ttl !== null){             this.client.expire(key, granularity.ttl);         }     } }; //returns a key based on granularitu and timestamp TimeSeries.prototype._getKeyName = function(granularity, timestampInSeconds){     var roundedTimestamp = this._getRoundedTimestamp(timestampInSeconds, granularity.duration);     return [this.namespace, granularity.name, roundedTimestamp].join(':'); }; //returns a normalized timestamp by granularity duration. //For example, all inserts that happen in the first minute of an hour are stored //in a key like "namespace:1min:0". All inserts from the second minute are stored //in the "namespace:1min:60", and so on TimeSeries.prototype._getRoundedTimestamp = function(timestampInSeconds, precision){     return Math.floor(timestampInSeconds / precision) * precision; }; //executes a callback by passing an array of data points TimeSeries.prototype.fetch = function(granularityName, beginTimestamp, endTimestamp, onComplete){     var granularity = this.granularities[granularityName];     var begin = this._getRoundedTimestamp(beginTimestamp, granularity.duration);     var end = this._getRoundedTimestamp(endTimestamp, granularity.duration);     var keys = [];     //iterate over all the timestamps in the specified range and save their values     //in the "keys" variable     for(var timestamp = begin; timestamp <= end; timestamp += granularity.duration){         var key = this._getKeyName(granularity, timestamp);         keys.push(key);     }     //the MGET command     this.client.mget(keys, function(err, replies){         var results = [];         //iterate over all replies         for(var i = 0; i < replies.length; i++){             var timestamp = beginTimestamp + i * granularity.duration;             //convert value to an integer             var value = parseInt(replies[i], 10) || 0;             //save timestamp and value in the "results" variable             results.push({timestamp: timestamp, value:value});         }         //execute callback passing the variables "granularityName" and "results"         onComplete(granularityName, results);     }); }; //make a function available as a module in Node.js exports.TimeSeries = TimeSeries;  | 
					
Now create a file called using-stock-timeseries.js, which will illustrate how to use our library. This file inserts stock quotes for a TimeSeries called “GAZPROM”, and then fetches values from a different granularities. Before inserting data, we remove all existing keys.
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40  | 
						var redis = require("redis"); var client = redis.createClient(); //the FLUSHALL command //removes all of the data from Redis client.flushall(); var timeseries = require("./stock-timeseries"); //create a TimeSeries object passing the redis client and the "GAZPROM" namespace //as an argument var StocksGazprom = new timeseries.TimeSeries(client, "GAZPROM"); //this timestamp value was chosen to make it easier to read the output var beginTimestamp = 0; //execute the insert function StocksGazprom.insert(beginTimestamp, 10); //execute the insert function, passing a timestamp that is 1 second after "beginTimestamp" StocksGazprom.insert(beginTimestamp + 1, 11); StocksGazprom.insert(beginTimestamp + 2, 12); StocksGazprom.insert(beginTimestamp + 3, 13); StocksGazprom.insert(beginTimestamp + 4, 14); //callback for displaying the output of the "fetch" function function displayResults(granularityName, results){     console.log("Results from", granularityName,":");     console.log("Timestamp   | Value");     console.log("----------  | ------");     for(var i = 0; i < results.length; i++){         console.log('\t' + results[i].timestamp + '\t' + results[i].value);     }     console.log(); } //retrieve an interval of 5 seconds StocksGazprom.fetch("1sec", beginTimestamp, beginTimestamp + 4, displayResults); //retrieve an interval of 5 minutes StocksGazprom.fetch("1min", beginTimestamp, beginTimestamp + 4, displayResults); client.quit();  | 
					
Now run your Redis server via redis-server. Then run node using-stock-timeseries.js. You should see the following output:
That’s all for today 🙂
