Redis中的复合主键等价物

时间:2017-05-01 15:48:45

标签: redis composite-primary-key nosql

我是nosql数据库的新手,所以请原谅我的sql心态,但我希望存储可以通过2个密钥之一“查询”的数据。这是结构:

{user_id, business_id, last_seen_ts, first_seen_ts} 

如果这是一个sql DB,我会使用user_id和business_id作为主要复合键。我正在寻找的那种查询是

1.'get all business_id = x'

2.'get all user_id = x'

任何提示?我不认为我可以基于上面的2种检索类型制作简单的二级索引。我查看了像'zadd'和'zrange'这样的命令,但这里没有涉及任何排序。

对我来说,Redis的用例是减轻对我的SQL数据库的写入和读取,同时该程序计算(以redis进行存储)最终将写入SQL DB的内容。

2 个答案:

答案 0 :(得分:4)

注意:鉴于OP的自称体验,这个答案是出于教育目的而故意简化的。

(其中之一)您需要了解的关于Redis的第一件事是您设计数据,因此每个查询都将被您认为是主键访问的内容。从这个意义上说,将Redis的键空间(全局字典)想象成这样的关系表是很方便的:

CREATE TABLE redis (
  key    VARCHAR(512MB) NOT NULL,
  value  VARCHAR(512MB),
  PRIMARY KEY (key)
);

注意:在Redis中,值当然不仅仅是一个字符串。

牢记这一点,与其他数据规范化的数据库模型不同,您希望Redis准备好有效地处理两个查询。这意味着您将保存数据两次:一次是在允许按ID搜索业务的主键下,另一次允许按用户ID查询。

要回答第一个查询(“'get all where business_id = x'”),您希望拥有包含相关数据的每个x的密钥(在Redis中我们使用冒号,':',作为约定的分隔符) - 因此,对于x = 1,您可能会调用您的键business:1,对于x = a1b2c3 business:a1b2c3等等。

每个这样的business:x键可以是Redis集,其中每个成员代表元组的其余部分。所以,如果数据类似于:

{user_id: foo, business_id: bar, last_seen_ts: 987, first_seen_ts: 123}

您将使用Redis存储它,例如:

SADD business:bar foo

注意:您可以使用任何所需的序列化,Set成员只是字符串。

有了这个,回答第一个查询只是SMEMBERS business:bar(或SSCAN更大的集合)。

如果您已经完成,则您已经知道如何提供第二个查询。首先,为user:foo的每个用户(例如SADD user:foo bar)使用Set。然后SMEMBERS / SSCAN,你几乎回家了。

您需要的最后一件事是另一组键,但这次您可以使用Hashes。每个这样的Hash将存储元组的附加信息,即时间戳。我们可以使用由商务和用户ID组成的“主键”(反之亦然),如下所示:

HMSET foo:bar first 123 last 987

从第一个或第二个查询中获得结果后,您可以获取相关哈希的内容以完成查询(假设查询也返回时间戳)。

答案 1 :(得分:3)

在Redis中执行此操作的惯用方法是对要执行的每种查询使用SET。 在您的情况下,您将创建:

  • 每个元组的哈希值(user_id,business_id,last_seen_ts,first_seen_ts)
  • 一个名称为user:<user_id>:business:<business_id>的集合,用于存储此用户和此商家的哈希键(您必须使用SADD添加哈希的ID)

然后,要获取给定用户和业务的所有数据,您必须首先获取SET内容SMEMBERS,然后GET每个HASH获取其ID在SET