I have a mapping that boils down to the following (unrelated fields removed):
mapping
indexes :id, type: 'integer', index: :not_analyze
indexes :first_name, boost: 5, type: 'string', analyzer: 'snowball'
indexes :votes, type: 'integer', index: :not_analyzed
end
At the moment I'm calculating ranking via postgres, so that given the following entries:
| first_name | votes |
----------------------
| Andy | 5 |
| Barry | 8 |
| Carl | 5 |
| Derek | 1 |
Using postgres, I can get the following:
| first_name | votes | rank |
-----------------------------
| Barry | 8 | 1 |
| Andy | 5 | 2 |
| Carl | 5 | 2 |
| Derek | 1 | 4 |
Is it possible somehow calculate this ranking via elasticsearch?
Redis is indeed an ideal solution for leaderboards. While it is introducing another technology, if you're using AWS, note that ElastiCache managed Redis was just launched this week.
Generic Redis commands would be:
Then to get the leaderboard with most votes as highest ranked:
Refer to the Redis docs for ZREVRANGE for more details.
For Ruby on Rails, I'd encourage you to look at my redis-objects gem which is popular since it easily integrates with ActiveRecord. Assuming you have a table with a
votescolumn as shown, you could update the ranking on save:Then retrieve the leaderboard:
In this example, this will return
idvalues which you could then use to retrieve records as follows. (You could also storefirst_nameor some other unique value.)You can paginate through results with
revrangeby passing different start/end values:You could easily wrap this in a
self.method in User that retrieved a page of rankings from Redis and returned the DB records accordingly.