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.id26で、前に最大10個のコメント、後に最大10個のコメントがあります。

コメントを変更してそのオフセットを表示するにはどうすればよいですか?

4

2 に答える 2

2

単純に聞こえますが、これで最高のパフォーマンスを実現するのは難しいことです。いずれにせよ、データベースに作業を任せる必要があります。これは、クライアント側ですべての行をフェッチしてフィルター/ソートするよりも桁違いに高速です。

「前」と「後」が小さい/大きいを意味comment.idし、ID スペースにギャップがある可能性があるとさらに想定している場合、この1 つのクエリですべてを実行する必要があります。

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 個のコメントを返します。存在しない場合は少なくなります。<=クエリの 2 番目のレグで使用してUNION ALL、選択したコメント自体を含めます。

行を並べ替える必要がある場合は、上に別のクエリ レベルを追加しますORDER BY

テーブルの次の 2 つのインデックスと組み合わせると、非常に高速になるはずですcomment

  • 1 つ(id)- おそらく自動的に主キーがカバーされます。
  • ワンオン(group_id, id)

読み取り専用データの場合、これをさらに高速化するギャップのない行番号を持つマテリアライズド ビューを作成できます。

この密接に関連する回答で、括弧、インデックス、およびパフォーマンスに関する詳細な説明。

于 2013-01-09T01:48:06.267 に答える
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)
于 2013-01-08T22:15:28.263 に答える