简体   繁体   English

Rails 组按用户上次创建的帖子或上次创建的评论排序

[英]Rails group order by user last created post or last created comment

I have the following relationship, a discussion which has_many posts which has_many comments我有以下关系,一个讨论里面有_很多帖子里面有_很多评论

I am trying to implement a personalised user dashboard which orders lastest discussions depending on the user very last change on a particular discussion, so if a user makes a post on a discussion, this discussion should be on the top of the dashboard and if a user makes a comment on any of the posts in a given discussion, this discussion should also now be on the top of his dashboard.我正在尝试实现一个个性化的用户仪表板,该仪表板根据用户对特定讨论的最后更改来排序最新的讨论,因此如果用户在讨论中发帖,则该讨论应位于仪表板的顶部,如果用户对给定讨论中的任何帖子发表评论,此讨论现在也应位于他的仪表板顶部。

Until now i can only get them to work separately, so i am struggling to combine them.到目前为止,我只能让它们分开工作,所以我正在努力将它们结合起来。

Only order by last Post:只能按最后一个帖子订购:

@discussions = Discussion.joins(:posts).where(posts: {user: current_user}).group('discussions.id').order('MAX(posts.created_at) DESC')

Only order by last Comment:只能按最后评论订购:

@discussions = Discussion.joins(:comments).where(comments: {user: current_user}).group('discussions.id').order('MAX(comments.created_at) DESC')

My Attempt to combine them which doesn't work:我尝试将它们结合起来但不起作用:

@discussions = Discussion.joins(:posts,:comments).where(posts: {user: current_user}).where(comments: {user: current_user}).group('discussions.id').order('MAX(posts.created_at) DESC', 'MAX(comments.created_at) DESC')

This only works depending on what i write on the .order but both never work..这仅取决于我在 .order 上写的内容,但两者都不起作用。

Any help will be much appreciated or any other way of achieving the purpose is also welcome!任何帮助将不胜感激,也欢迎任何其他实现目的的方式!

Update:更新:

A kind user helped me get a bit further but still not quite the results i am looking for一位好心的用户帮助我走得更远,但仍然不是我想要的结果

@discussions = Discussion.joins(:posts,:comments).where(posts: {user: current_user}).where(comments: {user: current_user}).group('discussions.id').order('GREATEST(MAX(posts.created_at), MAX(comments.created_at)) DESC')

The problem here is, that it only works if both a post and a comment exist within a discussion, but i want it to be if either is created the discussion list should be updated with the most recent changed discussion on top.这里的问题是,它只有在讨论中同时存在帖子和评论时才有效,但我希望它是,如果创建了任何一个,讨论列表应该更新为顶部最新更改的讨论。

query = """
SELECT discussions.*, MAX(sub2.MostRecentDate)
FROM discussions INNER JOIN (
  SELECT posts.id, posts.discussion_id,
    CASE
      WHEN sub1.MostRecentCommentDate IS NULL OR posts.updated_at >= sub1.MostRecentCommentDate THEN posts.updated_at
      ELSE sub1.MostRecentCommentDate
    END AS MostRecentDate
  FROM posts LEFT OUTER JOIN (
    SELECT comments.post_id, MAX(comments.updated_at) AS MostRecentCommentDate
    FROM comments
    WHERE comments.user_id = ?
    GROUP BY comments.post_id
  ) AS sub1
  ON sub1.post_id = posts.id AND posts.user_id = ?
) AS sub2
ON discussions.id = sub2.discussion_id
GROUP BY discussions.id
ORDER BY MAX(sub2.MostRecentDate) DESC
"""

Discussion.find_by_sql(Discussion.send(:sanitize_sql_array, [query, current_user.id, current_user.id]))

First, get maximum of updated_at on comments table grouped by post_id首先,在按post_id分组的评论表上获取最大的updated_at

SELECT comments.post_id, MAX(comments.updated_at) AS MostRecentCommentDate
FROM comments
GROUP BY comments.post_id AS sub1

Result:

|post_id|MostRecentCommentDate|
|-------|---------------------|
|  ...  |        ....         |

Next, left joins posts table with the result table above and compare the sub1.MostRecentCommentDate with posts.updated_at to get the final MostRecentDate接下来,左连接posts表和上面的结果表,比较sub1.MostRecentCommentDateposts.updated_at以获得最终的MostRecentDate

SELECT posts.id, posts.discussion_id,
  CASE
    WHEN sub1.MostRecentCommentDate IS NULL OR posts.updated_at >= sub1.MostRecentCommentDate THEN posts.updated_at
    ELSE sub1.MostRecentCommentDate
  END AS MostRecentDate
FROM posts LEFT OUTER JOIN (
...
) AS sub2

Result:

|discussion_id|MostRecentDate|
|-------------|--------------|
|     ...     |     ....     |

Finally, joins the discussion table with result table sub2 .最后,将讨论表与结果表sub2

SELECT discussions.*, MAX(sub2.MostRecentDate) 
FROM discussions 
INNER JOIN (
...
) AS sub2
ON discussions.id = sub2.discussion_id
GROUP BY discussions.id
ORDER BY MAX(sub2.MostRecentDate) DESC

Will give us a table of discussions order by sub2.MostRecentDate sub2.MostRecentDate为我们提供讨论顺序表

Note:笔记:

  1. The return value of find_by_sql() is an array not an ActiveRecord_Relation . find_by_sql()的返回值是一个数组而不是ActiveRecord_Relation

  2. The reason of calling sanitize_sql_array is to safely pass parameter to the raw query.调用sanitize_sql_array的原因是为了安全地将参数传递给原始查询。 Reference here参考这里

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM