2013-08-28 33 views
4

我有歸結爲以下(去除不相關的領域)的映射:排行榜排名通過elasticsearch(含輪胎)

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計算這個排名?

+2

你有沒有想過使用redis?這對於這樣的事情來說是完美的。對於彈性搜索,我會給他們的「排序」文檔進行閱讀:http://www.elasticsearch.org/guide/reference/api/search/sort/ –

+0

排名是相對於當前結果計算的,還是總計整個數據集?例如,在你的數據集中還有'薩拉'有10票,誰將因此排名1與不同的查詢/過濾器? – Phil

+0

正如@DamienRoche所說,Redis是這類東西的完美工具(假設票數和頻繁變化)。我不會想到ElasticSearch。 – Damien

回答

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 
+0

如果OP也在尋找與排名相匹配的分頁,那麼在ruby中排序可能不是一種選擇。 – rubish

3

Redis的確實是排行榜的理想解決方案。在引入另一項技術的同時,如果您使用的是AWS,請注意,ElastiCache託管Redis的產品爲just launched this week

通用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寶石,它很容易與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的排名頁面,並相應地返回數據庫記錄。