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
votes
column as shown, you could update the ranking on save:Then retrieve the leaderboard:
In this example, this will return
id
values which you could then use to retrieve records as follows. (You could also storefirst_name
or some other unique value.)You can paginate through results with
revrange
by 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.