仅供参考:Redis n00b。
我需要在我的网络应用中存储搜索字词。
每个术语都有两个属性:" search_count" (整数)和" last_searched_at" (时间)
示例I&尝试过:
Redis.hset("search_terms", term, {count: 1, last_searched_at: Time.now})
我可以想到一些不同的方法来存储它们,但没有好的方法来查询数据。我需要生成的报告是过去30天内的最佳搜索字词"。在SQL中,这将是一个where子句和一个order by。
我如何在Redis中做到这一点?我应该使用不同的数据类型吗?
提前致谢!
答案 0 :(得分:4)
我会考虑两个有序集。
提交搜索term
后,获取当前的timestamp
和:
zadd timestamps timestamp term
zincrby counts 1 term
以上两个操作应该是原子的。
然后查找给定时间间隔timestamp_from
,timestamp_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)。
答案 1 :(得分:2)
取决于您想要优化的内容。假设您希望能够非常快速地运行该查询并且不介意花费一些内存,我将按照以下方式执行此操作。
$search_term -> $count
的散列,其中$ count是第二次看到$ search_term的次数。这样,您可以使用ZRANGE $time_int_key 0 $m
在O(log(N)+ m)时间内获取最顶层搜索([WITHSCORES],如果您想要搜索它们的金额)。这非常便宜,能够在Redis中以任意频率运行几乎任何合理的m并始终实时更新数据。