Ruby on rails 通过elasticsearch排名排行榜(带轮胎)
我有一个映射,可以归结为以下内容(删除了不相关的字段): 目前,我正在通过postgres计算排名,因此考虑到以下条目:Ruby on rails 通过elasticsearch排名排行榜(带轮胎),ruby-on-rails,
elasticsearch,tire,Ruby On Rails,
elasticsearch,Tire,我有一个映射,可以归结为以下内容(删除了不相关的字段): 目前,我正在通过postgres计算排名,因此考虑到以下条目: | first_name | votes | ---------------------- | Andy | 5 | | Barry | 8 | | Carl | 5 | | Derek | 1 | 使用postgres,我可以获得以下信息: | first_name | votes | rank
| first_name | votes |
----------------------
| Andy | 5 |
| Barry | 8 |
| Carl | 5 |
| Derek | 1 |
使用postgres,我可以获得以下信息:
| first_name | votes | rank |
-----------------------------
| Barry | 8 | 1 |
| Andy | 5 | 2 |
| Carl | 5 | 2 |
| Derek | 1 | 4 |
是否可以通过elasticsearch计算排名?我不认为elasticsearch是这样做的,因为更新单个文档需要重新计算所有排名值。据我所知,这是不可能的 相反,一旦得到结果,您可以使用Ruby计算排名,如下所示:
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
scores={:a=>5,:b=>8,:c=>5,:d=>1}
scores.values.sort{| a,b | abb}。点击do | sorted|u分数|
排序的|分数。每个{|投票|放入排序的|分数。索引(投票)+1}
结束
Redis确实是排行榜的理想解决方案。当它引入另一种技术时,如果您使用的是AWS,请注意ElastiCache管理的Redis是
通用Redis命令将是:
zadd votes 5 "Andy"
zadd votes 8 "Barry"
zadd votes 5 "Carl"
zadd votes 1 "Derek"
然后以最高排名获得最多投票的排行榜:
zrevrange votes 0 -1
有关更多详细信息,请参阅
对于RubyonRails,我鼓励您看看我的gem,它很受欢迎,因为它很容易与ActiveRecord集成。假设您有一个带有投票
列的表,如图所示,您可以在保存时更新排名:
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
在本例中,这将返回id
值,您可以使用这些值来检索记录,如下所示。(您还可以存储名字
或其他一些唯一值。)
通过传递不同的开始/结束值,可以使用revrange
对结果进行分页:
User.rank.revrange(0, 9)
User.rank.revrange(10, 19)
您可以轻松地将其包装在用户的
self.
方法中,该方法从Redis检索一页排名并相应地返回DB记录。您想过使用Redis吗?这是完美的东西像这样。对于elasticsearch,我会仔细阅读他们的排序文档:排名是相对于当前结果计算的,还是整个数据集的总和?例如,在你的数据集中是否也有拥有10张选票的“Sarah”,因此谁会用不同的查询/筛选排名第一?正如@DamienRoche所说,Redis是这类东西的完美工具(假设投票数和排名经常变化)。我没有想到ElasticSearch会这么做。如果OP也在寻找分页和排名,那么ruby中的排序可能不是一个选项。
User.rank.revrange(0, -1)
ids = User.rank.revrange(0, -1)
users = User.where(id: ids).all
User.rank.revrange(0, 9)
User.rank.revrange(10, 19)