最近在学习 Redis,学的时候尝试写一个博客程序,第一次用 NoSQL,用起来还是有一些问题的,其中主要的就是:从 RDB 到 NoSQL 思想的转变,处理问题的思想不一样。

接下来说一个我遇到的一个问题,就是不同对象之间的关联问题,就拿文章便签来举例。

在关系型数据库(以MySQL为例)中,我们用一下方法处理,直接看 SQL:

文章表:

create table tb_post(
    post_id bigint not null primary key auto_increment,
    post_title varchar(100) not null default '',
    post_content text
)

标签表:

create table tb_tag(
    tag_id bigint not null primary key auto_increment,
    tag_name varchar(20)
)

文章和标签是多对多关系,所以再建立一个关联表:

create table tb_post_tag(
    post_tag_id bigint not null primary key auto_increment,
    post_id bigint not null,
    tag_id bigint not null
)

下面就是 Redis 的实现方法:

在用之前,我查了一下网上大家的做法,在 Redis 网站上一篇文章叫 《A fifteen minute introduction to Redis data types》,里面介绍了 Redis 的集中数据类型,其中介绍集合(Sets)类型的段落中有这么一句话:

Sets are very good for expressing relations between objects. For instance we can easily use Redis Sets in order to implement tags.

说的很清楚了,这种关联关系可以用集合(Sets)来实现,而且给出的例子也是文章和标签的,我就不献丑了,直接上原文中的例子:

A simple way to model this is to have a Set for every object containing its associated tag IDs, and a Set for every tag containing the object IDs that have that tag. For instance if our news ID 1000 is tagged with tag 1,2,5 and 77, we can specify the following five Sets - one Set for the object’s tags, and four Sets for the four tags:

$ redis-cli sadd news:1000:tags 1
(integer) 1
$ redis-cli sadd news:1000:tags 2
(integer) 1
$ redis-cli sadd news:1000:tags 5
(integer) 1
$ redis-cli sadd news:1000:tags 77
(integer) 1
$ redis-cli sadd tag:1:objects 1000
(integer) 1
$ redis-cli sadd tag:2:objects 1000
(integer) 1
$ redis-cli sadd tag:5:objects 1000
(integer) 1
$ redis-cli sadd tag:77:objects 1000
(integer) 1

To get all the tags for a given object is trivial:

$ redis-cli smembers news:1000:tags
1. 5
2. 1
3. 77
4. 2

上面的新闻(news),就想当与我们上文中的 post,这么实现就很清楚了。

最后推荐下这篇文章: 《A fifteen minute introduction to Redis data types》,非常值得一读。