如何根据特定记录周围的偏移量获取记录?

时间:2013-01-08 21:59:31

标签: ruby-on-rails ruby-on-rails-3 postgresql postgresql-9.1

我正在构建一个搜索评论的搜索界面。当用户点击搜索结果(评论)时,我想显示周围的评论。

我的模特:

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条评论之后。

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

2 个答案:

答案 0 :(得分:2)

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

如果“之前”和“之后”表示更小/更大comment.id,我们进一步假设ID空间可能存在空白,此 一个 < / strong>查询应该全部执行:

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.

答案 1 :(得分: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)