如何在redis中构建1级嵌套注释?

时间:2011-10-03 17:00:31

标签: comments redis

我一直在努力寻找嵌套评论的数据结构(只有1级嵌套,例如facebook)

为了实现注释的非嵌套“提要”,我一直使用有序集来跟踪注释,使用得分作为时间戳,将成员用作包含渲染所需信息的json编码属性集评论。

所以添加评论可能如下所示:

zadd 'users:1:comments', 123456789, {body : 'hello'}

检索它就像这样简单:

zrevrange 'users:1:comments', 0, 20

为了支持嵌套的评论,我试图以某种方式扩展它 我已经用两种不同的方式集思广益,但每种方式都有问题:

1)

将comment_id添加到comment_id指向父评论的属性列表

zadd 'users:1:comments', 123456789, {id : 1, body : 'hello'}
zadd 'comments:1:comments', 123456789, {id : 2, body : 'nested hello', comment_id : 123 }

看起来像这样:

-hello
  -nested hello

这种方法的问题在于分页。例如,如果注释有20个嵌套注释,并且我只显示前10个注释,那么嵌套树将被截断(将检索父注释+ 9个嵌套注释)

2)

将嵌套的评论放入自己的Feed:

This is a parent comment
zadd 'users:1:comments', 123456789, {id: 1, body : 'hello'}
this is a nested comment
zadd 'comments:1:comments' 123456789, {id: 2, body : 'nested hello'} 

但是,在尝试显示用户的Feed时,这会导致N + 1次redis查询:

zrevrange 'users:1:comments', 0, 20
zrevrange 'comments:1:comments', 0, 20
zrevrange 'comments:2:comments', 0, 20
etc...

...更不用说嵌套注释可能不应该用范围选择。

理想情况下,我希望这可以使用单个redis查询,但我不确定如何构建我的数据以便这样做。

想法?

1 个答案:

答案 0 :(得分:1)

我能想出的唯一方法就是使用Lists进行单一redis查询。

添加父项时,您只需将LPUSH添加到列表的顶部(左侧)即可。添加子评论时,您会使用类似LINSERT 'user:1:comments' AFTER parent-comment-data child-comment-data的内容。

这会导致redis搜索父注释数据并将子数据紧跟在其后面。这是一个O(N)操作,从顶部(左)到底部(右)完成,所以在列表的下方,父操作所需的时间越长,因此对于长列表这个可能会有问题(但如果您将列表/线程大小保持在4或5位数范围内,则应该没问题。)

然后,一个简单的LRANGE可以获取父母和孩子的最新评论,限制为任何数字。

您可以使用排序集中的分数值执行类似操作,为孩子提供的分数仅低于父分数。这可能会使插入显着复杂化,因为您可能会用尽两个父评论之间的可用分数,这意味着您必须运行操作来为许多(甚至大多数)评论重新分配分数。如果在每个插件上发生这种情况,您的插件可能会(不必要地)昂贵。