2013-05-17 25 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中以任何合理的频率运行,并且始终实时更新数据。

相关问题