如何通过ActiveRecord查询获取用户的可用任务列表?
优化你的未完成任务查询方案
嘿,我明白你想把原来的循环查询改成更高效的ActiveRecord语句,这就帮你搞定!
首先,回顾下你的模型关系:State属于User和Task,而User和Task都通过has_many :states关联。你要找的是当前用户所有状态为available的任务,完全可以用一次关联查询实现,避免原来循环带来的N+1性能问题。
推荐的查询方式
直接从Task模型出发,通过joins关联states表,再加上用户ID和状态条件:
@tasks = Task.joins(:states) .where(states: { user_id: current_user.id, value: :available }) .distinct
joins(:states):建立Task和State的关联查询,把两张表连起来where(states: { ... }):指定State表的筛选条件,因为你用了as_enum,直接用符号:available就可以,Rails会自动转换成对应的value_cd值(也就是你原来用的0).distinct:如果同一个任务可能对应多条State记录(虽然业务上应该不会,但加上更稳妥),用来去重,避免返回重复的Task对象
另一种从用户出发的写法
如果你习惯从current_user的角度查询,也可以用预加载避免N+1问题:
@tasks = current_user.states .where(value: :available) .includes(:task) .map(&:task) .uniq
这里includes(:task)会一次性加载所有关联的Task,比你原来的循环逐个加载高效很多,uniq同样用来去重。
为什么比原来的循环好?
原来的循环会先查询出所有符合条件的State记录,然后逐个加载对应的Task,这会触发N+1次SQL查询(1次查State,N次查每个State对应的Task)。而上面的两种方法都只会触发1-2次SQL查询,性能提升明显,尤其是数据量较大的时候。
内容的提问来源于stack exchange,提问作者adnan hajar
相关产品推荐
相关产品推荐

