如何在ActiveRecord的Building模型中实现含楼层编号数组的查询方法
如何用ActiveRecord查询实现Building模型的some_stuff类方法?
我来帮你搞定这个需求!基于你现有的Building和Floor关联模型,下面分两种常用数据库场景,给出用ActiveRecord查询实现目标方法的方案:
方案一:适用于PostgreSQL数据库
PostgreSQL原生支持数组聚合函数,能直接生成我们需要的楼层number数组:
class Building < ActiveRecord::Base has_many :floors def self.some_stuff left_joins(:floors) .select( "buildings.id as id", "buildings.url as url", "array_agg(floors.number) as numbers" ) .group("buildings.id, buildings.url") .map do |building| { id: building.id, url: building.url, numbers: building.numbers.compact # 移除无楼层时产生的nil值 } end end end
代码细节说明:
left_joins(:floors):确保即使没有关联楼层的建筑也能被查询到(如果只需要包含楼层的建筑,换成joins(:floors)即可)array_agg(floors.number):把每个建筑对应的所有楼层number聚合为一个数组group("buildings.id, buildings.url"):按建筑的唯一标识分组,保证每个建筑只返回一条结果map方法:将ActiveRecord对象转换成你需要的哈希格式,compact处理无楼层时数组中的nil值
方案二:适用于MySQL数据库
MySQL没有原生数组类型,我们需要先用字符串拼接再转成数组:
class Building < ActiveRecord::Base has_many :floors def self.some_stuff left_joins(:floors) .select( "buildings.id as id", "buildings.url as url", "GROUP_CONCAT(floors.number SEPARATOR ',') as numbers" ) .group("buildings.id, buildings.url") .map do |building| { id: building.id, url: building.url, numbers: building.numbers.present? ? building.numbers.split(',').map(&:to_i) : [] } end end end
代码细节说明:
GROUP_CONCAT(floors.number SEPARATOR ','):把楼层number用逗号拼接成字符串split(',').map(&:to_i):将拼接后的字符串拆分成数组并转换为整数类型present?判断:处理无楼层时返回空数组的情况
额外提示
如果你的Building模型id是UUID类型(和示例中的格式一致),要确保数据库中id字段已配置为UUID类型,否则查询会返回数据库存储的原生id格式(比如整数id)。
内容的提问来源于stack exchange,提问作者Hungry Beast
相关产品推荐
相关产品推荐

