Ruby on Rails:如何查询含至少1个分类14公司的城市
Rails 查询关联指定分类公司的城市实现方案
需求
获取所有满足以下条件的City记录:
- 城市至少关联1家Company记录
- 关联的Company的
category_id为指定值(示例为14,也支持动态传入@category.id)
现有模型关联关系
三个模型均为多对多的has_and_belongs_to_many关联:
class City < ApplicationRecord has_and_belongs_to_many :categories has_and_belongs_to_many :companies end class Company < ApplicationRecord has_and_belongs_to_many :categories has_and_belongs_to_many :cities end class Category < ApplicationRecord has_and_belongs_to_many :companies has_and_belongs_to_many :cities end
原有写法问题
你当前写的查询存在两个明显问题:
# 错误代码 City.includes(:companies).where('companies.category_id' => @category.id)
- 用
includes做关联表条件查询时,未显式声明引用关联表,多数Rails版本会抛出找不到companies表的SQL错误 - 未做去重处理:如果同一个城市下有多家符合分类要求的公司,查询结果会重复返回同一个城市记录
正确实现
场景1:仅需筛选城市,不需要后续访问关联的公司数据(性能最优)
直接用joins做内连接,天然过滤掉无匹配关联公司的城市,加distinct去重即可:
# 固定category_id为14的写法 City.joins(:companies).where(companies: { category_id: 14 }).distinct # 动态传入分类id的写法 City.joins(:companies).where(companies: { category_id: @category.id }).distinct
说明:
joins默认生成INNER JOIN语句,只会返回存在匹配关联公司的城市,完全满足「至少关联1家符合条件公司」的要求;用哈希形式的where条件companies: { category_id: xxx }比字符串写法更安全,不会出现SQL语法兼容问题。
场景2:查询后需要访问每个城市的关联公司列表(避免N+1查询)
如果后续逻辑需要遍历城市读取对应的公司数据,用includes搭配references,或者直接用eager_load预加载关联数据:
# 写法1:includes + references City.includes(:companies) .where(companies: { category_id: @category.id }) .references(:companies) .distinct # 写法2:直接用eager_load City.eager_load(:companies) .where(companies: { category_id: @category.id }) .distinct
内容的提问来源于stack exchange,提问作者lkjr23ufby234
相关产品推荐
相关产品推荐

