Rails中如何合并同一模型的两类关联查询结果并支持排序分页
优化方案
你原有实现的可优化点:
- 额外执行了一次
pluck(:id)查询,将图片ID加载到Ruby内存,数据量大时会有明显的内存占用和性能损耗 - 直接用ID数组做IN查询,当ID数量过多时会降低SQL执行效率
以下两种实现均返回ActiveRecord::Relation对象,原生支持后续链式调用排序、分页方法:
方案1:简化OR查询(改动最小,适配原有逻辑)
利用ActiveRecord自动将Relation转为子查询的特性,去掉pluck步骤,同时保证OR两边的查询结构完全一致即可正常调用or方法:
def viewable_pictures organization.pictures.where(public: true).or( organization.pictures.where(id: pictures) ) end
生成的SQL会自动把当前用户关联的图片查询转为IN子查询,全程只有一次SQL执行,无需把ID加载到Ruby层。
方案2:LEFT JOIN实现(性能更优,适合数据量大的场景)
通过左连接用户和图片的多对多关联表,直接在SQL层做条件判断,避免子查询开销:
def viewable_pictures Picture.left_joins(:users) .where(organization_id: self.organization_id) .where("pictures.public = ? OR users.id = ?", true, self.id) .distinct end
left_joins关联用户和图片的多对多关联表,保留所有符合机构条件的图片- 条件直接判断「图片公开」或「图片关联的用户为当前用户」两个权限规则
distinct用来去重,避免同一张图片同时满足两个条件、或关联多个用户时返回重复记录
内容的提问来源于stack exchange,提问作者Gavin Esplin
相关产品推荐
相关产品推荐

