2013-05-17 86 views
2

供參考:Redis n00b。我應該如何在Redis中對此進行建模?

我需要在我的網絡應用程序中存儲搜索條件。

每個學期都會有兩個屬性: 「search_count」(整數)和 「last_searched_at」(時間)

例子我已經試過:

Redis.hset("search_terms", term, {count: 1, last_searched_at: Time.now}) 

我能想到的幾種不同的方式存儲它們,但沒有好的方法來查詢數據。我需要生成的報告是「過去30天內的熱門搜索字詞」。在SQL中,這將成爲where子句和order by。

我該如何在Redis中做到這一點?我應該使用不同的數據類型嗎?

在此先感謝!

回答

4

我會考慮兩個有序集。

當搜索term提交,獲得當前timestamp和:

zadd timestamps timestamp term 
zincrby counts 1 term 

,上述兩個操作應該是原子的。

然後找到在給定的時間間隔timestamp_fromtimestamp_to所有條款:

zrangebyscore timestamps timestamp_from timestamp_to 

你得到這些後,環比他們從counts得到計數。

或者,我很好奇你是否可以使用zunionstore。下面是我在Ruby中的測試:

require 'redis' 

KEYS = %w(counts timestamps results) 
TERMS = %w(test0 keyword1 test0 test1 keyword1 test0 keyword0 keyword1 test0) 

def redis 
    @redis ||= Redis.new 
end 

def timestamp 
    (Time.now.to_f * 1000).to_i 
end 

redis.del KEYS 

TERMS.each {|term| 
    redis.multi {|r| 
    r.zadd 'timestamps', timestamp, term 
    r.zincrby 'counts', 1, term 
    } 
    sleep rand 
} 

redis.zunionstore 'results', ['timestamps', 'counts'], weights: [1, 1e15] 

KEYS.each {|key| 
    p [key, redis.zrange(key, 0, -1, withscores: true)] 
} 

# top 2 terms 
p redis.zrevrangebyscore 'results', '+inf', '-inf', limit: [0, 2] 

編輯:在某些時候,你就需要清除counts集。類似於@Eli提出的(https://stackoverflow.com/a/16618932/410102)。

+0

你如何知道如何爲你所做的工作指定zunionstore的參數。我正在做以下工作,'redis.zunionstore('tmp',2,'some-zest','some-set','weights',0,1,'aggregate','max')'直到我找到你:)我在哪裏可以找到一些文件或相同的例子..或者我應該只是通過github上的代碼(例如在github上也沒有任何東西) – Akshay

+1

@Akshay我想我從github存儲庫中學到了它:https ://github.com/redis/redis-rb/search?utf8 =%E2%9C%93&q = zunionstore – akonsu

+0

明白了..謝謝:)當我查看redis.rb時,你的技術沒有響個不停:p – Akshay

2

取決於您想要優化的內容。假設你希望能夠快速運行該查詢,並且不介意花費一些內存,我會按如下所示執行操作。

  1. 爲每一秒鐘保持一個關鍵你看到一些搜索(如果你喜歡,你可以去粒度更細或更小)。密鑰應該指向$search_term -> $count的散列,其中$ count是在該秒鐘內看到$ search_term的次數。
  2. 爲每個需要數據的時間間隔(我們稱之爲$ time_int_key)保留另一個鍵(在您的情況下,這只是您的間隔是最近30天的一個鍵)。這應該指向一個已排序的集合,其中集合中的項目是您在過去30天內看到的所有搜索詞彙,並且排序的分數是他們在過去30天內看到的次數。
  3. 有一個後臺工作人員,每隔一秒就會爲30天前發生的第二次密鑰獲取密鑰,並通過附加的哈希循環。因爲在這樣的關鍵每$ SEARCH_TERM,它應該與$ SEARCH_TERM在$ time_int_key相關的分數減去$計數

這種方式,你可以使用ZRANGE $time_int_key 0 $m搶m個熱門搜索([WITHSCORES]如果你想要他們被搜索的數量)在O(log(N)+ m)時間。這足夠便宜,能夠在Redis中以任何合理的頻率運行,並且始終實時更新數據。

相關問題