Hey @Estev this is the perfect use case for Redis Sorted Sets :)
Where ever in your code you want to increment the various stats add the following:
for visits I would use:
\Redis::command('zincrby', ['sset:stats:' . date('Ymd:H'), 1, 'visits']);
For a Click:
\Redis::command('zincrby', ['sset:stats:' . date('Ymd:H'), 1, 'click']);
For a Sale:
\Redis::command('zincrby', ['sset:stats:' . date('Ymd:H'), 1, 'sales']);
Then when you want the info just use the following:
Redis::command('zrange', ['sset:stats:20161014:10', 0, -1, 'withscores']);
Here is a dump from a quick play in Tinker:
>>> use \Redis;
=> null
>>> Redis::command('zincrby', ['sset:stats:' . date('Ymd:H'), 1, 'visits']);
=> "1"
>>> Redis::command('zincrby', ['sset:stats:' . date('Ymd:H'), 1, 'visits']);
=> "2"
>>> Redis::command('zincrby', ['sset:stats:' . date('Ymd:H'), 1, 'visits']);
=> "3"
>>> Redis::command('zincrby', ['sset:stats:' . date('Ymd:H'), 1, 'click']);
=> "1"
>>> Redis::command('zincrby', ['sset:stats:' . date('Ymd:H'), 1, 'click']);
=> "2"
>>> Redis::command('zincrby', ['sset:stats:' . date('Ymd:H'), 1, 'click']);
=> "3"
>>> Redis::command('zincrby', ['sset:stats:' . date('Ymd:H'), 1, 'visits']);
=> "4"
>>> Redis::command('zincrby', ['sset:stats:' . date('Ymd:H'), 1, 'visits']);
=> "5"
>>> Redis::command('zincrby', ['sset:stats:' . date('Ymd:H'), 1, 'sales']);
=> "1"
>>> Redis::command('zrange', ['sset:stats:' . date('Ymd:H'), 0, -1]);
=> [
"sales",
"click",
"visits",
]
>>> Redis::command('zrange', ['sset:stats:' . date('Ymd:H'), 0, -1, 'withscores']);
=> [
"sales" => "1",
"click" => "3",
"visits" => "5",
]
>>>
Advantages:
- Lighting fast
- Easy to implement
- Doesn't break existing functionality.
You can leave them around as long as you like and you will have instant access to past stats as well as real time (e.g. by using the zrange command with the current date / hour). As I said, this is a perfect use case for adding Redis to your stack.
And here is your Bonus!!!
To get Daily statistics, all you need to do is...
// Get a list of all the keys for Today - Real time! The keys command is a bit heavy, you could maintain a "LIST" with the stat keys.
$todaysKeys = Redis::command('keys', ['sset:stats:' . date('Ymd').':*']);
=> [ "sset:stats:20161014:11",
"sset:stats:20161014:01" ]
// Merge the information required for the command to work; Note the different Key shape
$redisParams = array_merge(['sset:stats:'.date('Ymd').'-daily', count($todaysKeys) ], $todaysKeys);
=> [ "sset:stats:20161014-daily",
2,
"sset:stats:20161014:11",
"sset:stats:20161014:01" ]
// Create the Daily statistics Sorted Set (the scores are summed)
>>> Redis::command('zunionstore', $redisParams);
=> 3
// Now get the daily stats...
Redis::command('zrange', ['sset:stats:'.date('Ymd').'-daily', 0, -1, 'withscores']);
=> [ "sales" => "1",
"click" => "3",
"visits" => "8" ]