2013-01-08 69 views
0

我正在构建搜索评论的搜索UI。当用户点击搜索结果(评论)时,我想显示周围的评论。如何根据特定记录的偏移量来获取记录?

我的模型:

Group (id, title) - A Group has many comments 
Comment (id, group_id, content) 

例如:

当用户点击与comment.id等于26.评论我会先找到该组所有的意见:

comment = Comment.find(26) 
comments = Comment.where(:group_id => comment.group_id) 

我现在拥有该团体的所有评论。然后我想要做的是显示comment.id 26,最多10条评论,10条评论。

如何修改注释以显示偏移量?

回答

0

喜欢的东西:

comment = Comment.find(26) 
before_comments = Comment. 
    where('created_at <= ?', comment.created_at). 
    where('id != ?', comment.id). 
    where(group_id: comment.group_id). 
    order('created_at DESC').limit(10) 
after_comments = Comment. 
    where('created_at >= ?', comment.created_at). 
    where('id != ?', comment.id). 
    where(group_id: comment.group_id). 
    order('created_at DESC').limit(10) 
+0

你如何确保只有得到正确的GROUP_ID的意见吗? – AnApprentice

+0

我很好奇,如果这是可能的一个查询与几个? – AnApprentice

+0

你或许可以写出一个复杂的SQL查询,它将一次完成所有上述操作,但是它的可读性会受到影响。 – gylaz

2

听起来很简单,但它的棘手得到这个最佳的性能。无论如何,你必须让数据库做这项工作。这比在客户端获取所有行和过滤/排序的速度要快一个数量级。

如果“之前”和“之后”你的意思是小/大comment.id,我们进一步假设,有可能在ID空间的差距,这一个查询应该做的一切:

WITH x AS (SELECT id, group_id FROM comment WHERE id = 26) -- enter value once 
(
SELECT * 
FROM x 
JOIN comment c USING (group_id) 
WHERE c.id > x.id 
ORDER BY c.id 
LIMIT 10 
) 
UNION ALL 
(
SELECT * 
FROM x 
JOIN comment c USING (group_id) 
WHERE c.id < x.id 
ORDER BY c.id DESC 
LIMIT 10 
) 

我会给你解释一下Ruby语法,那不是我的专业领域。

返回之前的10条评论和10条之后的评论。如果存在的话更少。在UNION ALL查询的第二段中使用<=以包含所选评论本身。

如果您需要排序的行,请在ORDER BY的顶部添加另一个查询级别。

应该是非常快的,结合这两个指标comment

  • 一个上(id) - 可能会自动覆盖的主键。
  • 一个上(group_id, id)

对于只读的数据,你可以创建一个间隙少的行数,将使这甚至更快的物化视图。

More explanation about parenthesis, indexes, and performance in this closely related answer.

相关问题