我有一个映射,归结为以下(删除了不相关的字段):
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
目前我正在通过postgres计算排名,因此给出以下条目:
| 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计算此排名?
答案 0 :(得分:3)
我不相信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
答案 1 :(得分:3)
Redis确实是排行榜的理想解决方案。虽然它引入了另一项技术,但如果您使用的是AWS,请注意ElastiCache管理的Redis是just launched this week。
Generic Redis命令将是:
zadd votes 5 "Andy"
zadd votes 8 "Barry"
zadd votes 5 "Carl"
zadd votes 1 "Derek"
然后获得排名最高的排行榜:
zrevrange votes 0 -1
有关详细信息,请参阅Redis docs for ZREVRANGE。
对于Ruby on Rails,我建议你看一下受欢迎的redis-objects gem,因为它很容易与ActiveRecord集成。假设您有一个显示votes
列的表格,您可以在保存时更新排名:
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
然后检索排行榜:
User.rank.revrange(0, -1)
在此示例中,这将返回id
值,然后您可以使用这些值来检索记录,如下所示。 (您还可以存储first_name
或其他一些唯一值。)
ids = User.rank.revrange(0, -1)
users = User.where(id: ids).all
您可以通过传递不同的开始/结束值来对结果revrange
进行分页:
User.rank.revrange(0, 9)
User.rank.revrange(10, 19)
您可以轻松地将此包装在用户中的self.
方法中,该方法从Redis检索排名页面并相应地返回数据库记录。