Elasticsearch leader rating (with tire)

I have a mapping that boils down to the following (deleted unrelated fields):

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 

I am currently calculating the rating via postgres, so 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 to somehow calculate this rating through elasticsearch?

+4
source share
2 answers

I do not believe that ElasticSearch is the place, since updating one document will require recalculation of all rank values. Impossible as far as I can judge.

Instead, once you get the results, you can use Ruby to calculate the ranking with something like this:

 scores = {:a=>5, :b=>8, :c=>5, :d=>1} scores.values.sort{|a,b| a <=> b}.tap do |sorted_scores| sorted_scores.each{|vote| puts sorted_scores.index(vote)+1 } end 
+3
source

Redis is truly the perfect solution for leaders. While you are introducing another technology, if you are using AWS, please note that ElastiCache was running Redis, was just launched this week .

Common Redis Commands:

 zadd votes 5 "Andy" zadd votes 8 "Barry" zadd votes 5 "Carl" zadd votes 1 "Derek" 

Then, to get the top rated leaders:

 zrevrange votes 0 -1 

See Redis docs for ZREVRANGE for more details .

For Ruby on Rails, I would advise you to take a look at my redis-objects gem, which is popular as it integrates easily with ActiveRecord. Assuming you have a table with a votes column as shown, you can update the rating while saving:

 class User < ActiveRecord::Base include Redis::Objects sorted_set :rank, global: true after_save :update_rank def update_rank self.class.rank[id] = votes end end 

Then extract the leaderboard:

 User.rank.revrange(0, -1) 

In this example, this will return id values ​​that can then be used to retrieve the entries as follows. (You can also save first_name or another unique value.)

 ids = User.rank.revrange(0, -1) users = User.where(id: ids).all 

You can paginate with revrange by passing different start / end values:

 User.rank.revrange(0, 9) User.rank.revrange(10, 19) 

You can easily wrap this with the self. method self. in User, who received the ranking page from Redis and returned DB records accordingly.

+3
source

Source: https://habr.com/ru/post/1499476/


All Articles