简短回答:是的。
长答案:Redis 是一项了不起的技术,但它不是关系数据库。包括 Redis 在内的 NoSQL 是建立在数据需要根据使用的访问模式存储的前提下的。因此,要完成上述操作,您首先必须“正确”存储数据。
要存储表的行,您似乎需要使用 Hash 数据结构。在 Redis 的术语中,以下是为 UserID 123 创建用户密钥的方法:
HMSET user:123 id 123 name foo age 31
注 1: 在构造密钥名称时使用冒号 (':') 只是一种约定。
注 2: 而 ID 是已经是密钥名称的一部分,通常将其包含在 Hash 中的一个字段以便于访问。
同样,以下是创建消息密钥(ID 为 987)的方法:
HMSET message:987 id 987 userid 123 content bar importance 3
现在有趣的部分来了 :) Redis 没有 FK 或索引,因此您必须维护数据结构,以帮助您根据需要获取数据。对于您的第一个查询,最好的选择是保留一个排序集,其中成员是消息 ID,分数是重要性。因此这样做:
ZADD messages_by_importance 3 987
获取重要性大于 2 的消息内容将通过以下伪 Python 代码所示的两个操作完成:
messages = r.zrangebyscore('messages_by_importance', '(2', '+inf')
for msg in messages:
content = r.hget('message:' + msg, 'content')
do_something(content)
注 3: 这个 sn-p 非常幼稚,可以进行优化以获得更好的性能,但它应该为您提供基本的要点。
对于第二个查询,您首先需要找到 30 岁以上的用户 - 再次,应该使用相同的排序集技巧:
ZADD users_by_age 31 123
ZRANGEBYSCORE users_by_age (30 +inf
这将为您提供符合您条件的所有用户的列表,但您还需要跟踪(索引)每个用户的所有消息。为此,请使用 Set:
SADD user:123:messages 987
为了绑定所有内容,这里还有一个伪 sn-p:
users = r.zrangebyscore('users_by_age', '(30', '+inf')
for user in users:
messages = r.smembers('user:' + user + ':messages')
for msg in messages:
content = r.hget('message:' + msg, 'content')
do_something(content)
这应该足以让您入门,但是一旦您牢牢掌握了基础知识,请考虑优化这些流程。根据您的需要,使用流水线、Lua 脚本和更智能的索引可以轻松获得收益......如果您需要任何进一步的帮助 - 只需询问:)