我有一个论坛。每个用户都有帖子和回复。每个帖子都有回复。每当一个用户查看一个帖子时,我都会在Views表中创建一条记录(或者用最后一个reply_id更新它)。假设一个帖子还没有回复,那么我只保存user_id和post_id。如果有对帖子的回复,那么我保存user_id、post_id和帖子查看时最后一个回复的reply_id。
我试图创建一个页面“搜索未读的帖子”,向用户显示任何他们没有读过的帖子,或者如果有一个新的回复他们已经看过的帖子。我相信你们大多数人都熟悉这个原则,因为大多数论坛引擎都有这种搜索,但我想确保不要留下任何问题。
以下是关联(去除了所有权限检查和其他关联):
class User < ActiveRecord::Base
has_many :posts
has_many :views
end
class Post < ActiveRecord::Base
belongs_to :user
has_many :replies
has_many :views
has_one :latest_reply, :order => "created_at DESC", :class_name => "Reply", :conditions => { :replystatus => 'published' }
end
class Reply < ActiveRecord::Base
belongs_to :post
belongs_to :user
has_many :views
end
class View < ActiveRecord::Base
belongs_to :post
belongs_to :reply
belongs_to :user
end
我想知道如何只得到的职位,用户,要么,还没有阅读在所有(没有记录的意见),或职位latest_reply.id大于“视图”中保存的id。我已经想出了如何用sql编写这个查询(使用连接,子查询和联合),但我想知道是否有人知道用Rails的方式来做这件事。我猜一些智能(链接)范围将工作,但我只是不能把我的头周围。
5条答案
按热度按时间ukqbszuj1#
我给@BillyChan添加了评论re:发布和查看计数。
Re:latest_reply,我认为你应该把它作为一个范围推到Reply模型中:
然后,您可以将其作为文章访问。views.published.最新/回复views.published.最新的和比较,但你想。
aamkag612#
新答案
根据OP的评论,我意识到我误解了以前回答的问题。已读/未读跟踪是如此深入到用户级别。我没有这样的经验,但可以提供两个想法集思广益。
1.数据库方式。你保持你现在做的。但是对于每个新创建的帖子,您需要将每个用户的记录添加到View表中,每个用户的初始值为零视图计数。通过这个你可以使用SQL来检查哪些帖子对于某些用户是未读的。缺点是服务器的工作量会很大,表会很大,也许你可以使用cron来添加View记录,使用缓存来存储用户未读的帖子。
1.数组比较方式。在用户表中添加一个字段,用于存储用户查看的帖子ID。对于他查看的每个帖子,该字段将更新为添加的帖子ID。然后,当你显示一个普通的帖子列表(比如最近的帖子)时,你可以比较这个id是否在这个字段中(转换为数组),如果没有,将帖子标记为未读。要显示未读文章的完整列表,您可以使用SQL搜索不在此字段中的文章id(SELECT id FROM posts WHERE id NOT IN the_id_list_arrary)
你可以随意批评。
对问题理解错误,放弃原答案
我的建议是在Post中添加一个名为
view_count
的字段,默认值为0。每次向
View
表写入一条关于Post的新记录时,view_count
也会增加1。要搜索未读帖子,您可以简单地搜索view_count为0的帖子。
通过这种方法,你将保存大量的服务器资源查询,因为视图表将非常大,查询它的方式在你的问题是非常沉重的。
可选的未来增强功能:
1.您可以设计一个任务来通过View表重建view_count,并手动或通过cron运行它。
1.您甚至可以在将来添加view_count_month,view_count_year,view_count_all字段。有了重建机制,维护这些字段就很容易了。
毕竟,在我看来,基本的解决方案应该足够好了。
lsmepo6l3#
使用中介表是一种正确的方法,但它通常太重而无法处理,即使使用计数器缓存或其他东西(想象一下View表中的数百万条记录)。..).
因此,我可以提供一个更轻,更快的选择,没有任何连接表。
Post有一个属性:
last_viewed
(日期时间)。每次当用户查看帖子的回复时,属性会更新为特定回复的created_at
值(如果更新)。现在:
这种方法在论坛引擎中最常用。因为它很快。
**[更新]**所有用户和所有帖子和所有回复:
将属性添加到用户:
last_view_posts_at
(datetime)当用户打开该属性时,必须使用Post或Reply的created_at
值(如果较新)更新该属性。问题是你不能管理特定帖子和回复的读/未读,因为它依赖于时间戳。你必须使用`last_view_posts_at '。假设你有3条未读消息。之后,你打开最旧的,然后阅读最新的,在这种情况下,第二个(中间)将不会是'未读'了。
r7s23pms4#
我能够微调服务于我的问题的实际查询。下面是实际的查询(在这个例子中,user_id是硬编码的,但在控制器中,它是@current_user。id):
下面是我如何将它放在控制器中(将它作为一个范围移动到模型中):
我知道这并不漂亮,但我已经花了将近两天的时间来弄清楚如何使用这种“Rails方式”,现在必须这样做,因为我还有很多编码要做:)
如果任何人有任何提示或如何做到这一点的“Rails方式”或如何加快这个查询(这是令人惊讶的快),我会感谢您的所有输入。
ee7vknir5#
要获取用户的未读帖子,您可以在Post模型中使用以下范围:
这会触发所有帖子的JOIN,即使用户没有查看过任何帖子。此范围允许您过滤所有未读帖子,即使该用户尚未对帖子作出React。最近的回复总是与用户的React不同。您可以对特定用户使用GetUnreads作用域来获取该用户尚未阅读的所有帖子的列表我在我的site上使用了这个。