You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails 7中高效获取用户关联Applicant聊天记录的优化问询

优化方案:高效获取用户的所有聊天会话(Applicant记录)

原实现的核心问题

原代码会触发N+2次数据库查询(N为用户项目数量):

  1. 先查询当前用户的所有项目
  2. 遍历每个项目时,分别查询对应Applicant记录(N次查询)
  3. 合并数组后再次通过ID查询Applicant
    同时数组合并会额外占用内存,数据量越大性能损耗越明显。

方案1:单次SQL级联查询(最直接高效)

直接通过OR条件将两种场景(用户作为申请者、用户作为项目所有者)合并为一次数据库查询:

@chats = Applicant
  # 场景1:用户是申请者
  .where(user_id: current_user.id)
  # 场景2:用户是项目所有者,关联查询对应的Applicant
  .or(Applicant.joins(:project).where(projects: { user_id: current_user.id }))
  # 按最后消息时间倒序
  .order(last_message: :desc)

优势

  • 仅触发1次SQL查询,彻底消除N+1问题
  • 逻辑清晰,直接对应业务需求

方案2:封装User模型关联(更优雅的复用)

在User模型中定义自定义关联,把聊天会话的查询逻辑封装起来,方便后续多处调用:

class User < ApplicationRecord
  # ... 现有代码 ...

  # 定义用户的所有聊天会话关联
  has_many :chat_applicants, ->(user) {
    where("applicants.user_id = ? OR projects.user_id = ?", user.id, user.id)
      .joins("LEFT JOIN projects ON projects.id = applicants.project_id")
      .distinct
  }, class_name: "Applicant"
end

调用时只需一行代码:

@chats = current_user.chat_applicants.order(last_message: :desc)

补充说明

  • 加入distinct是为了预防极端场景下的重复记录(比如用户既是某项目申请者又是所有者,业务上大概率不会出现,但可以提前规避)
  • 关联封装后,业务代码更简洁,逻辑复用性更强

内容的提问来源于stack exchange,提问作者Frub

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 19:40:07