【发布时间】:2015-11-30 02:24:21
【问题描述】:
我有一些 n + 1 个查询使我的网站的加载时间非常慢。这是一个类似于 Facebook 的社交媒体网站,n + 1 个查询的来源是朋友。详情 -
Friendships 表有 3 列 - User_id(发送请求的用户)、friend_id(收到请求的用户)和 pending,它是一个布尔值,表示友谊是否被接受。
好友请求是在我的用户模型中使用
实现的def friend_requests
friend_ids = Friendship.where('friend_id = ? AND pending = true', self.id).all
end
我特别需要友谊 ID,因为如果用户想要接受或拒绝请求,我需要更新待处理的布尔值。
Friendship 模型声明了一个 belongs_to => 朋友关联。
belongs_to :friend,
class_name: "User",
foreign_key: :friend_id,
primary_key: :id
n+1 的来源。对于视图,当我想获取用户收到的好友请求时,我还想包含发送请求的用户的姓名和头像。它看起来像这样 -
json.friend_requests @user.friend_requests.includes(friend: :name) do |friendship|
json.extract! friendship, :id, :user_id
json.name User.find(friendship.user_id).name # n + 1
json.profile_pic User.find(friendship.user_id).profile_pic # n + 1
end
我最初对 include(friend: :name) 的语法有一些疑问,但我已经尝试了this thread 中提到的所有排列,但它给了我
在用户上找不到名为“名称”的关联;也许你拼错了 是吗?
这是正确的,因为 name 是 User 的属性而不是关联。
我能想到的解决这个问题的唯一方法是将我的friend_requests 表更改为如下所示的find_by_sql 查询 -
SELECT f.id, f.user_id, f.friend_id, f.pending, users.name, users.profile_pic
FROM friendship AS f
JOIN users ON users.id = friendship.friend_id
WHERE f.friend_id = ? AND pending = true
它会给我用户的名字和 profile_pic,但我不想这样做,因为它看起来很脏,但更重要的是我想知道是否有更好、更智能的方法来做到这一点。
【问题讨论】:
标签: ruby-on-rails performance caching activerecord