如何将使用多字段select的Arel查询结果转换为哈希结构
实现方案
你原来的写法中 users[Arel.star].as("user") 不会生效,因为关系型数据库不支持将整表字段打包为单个复合字段返回,SELECT 表.* 会直接展开所有字段,无法直接得到user键对应的整行数据,需要在Ruby层手动组装,以下是3种常用实现方式:
方案1:直接遍历查询结果构造哈希(最简单,保留完整ActiveRecord对象功能)
在原有查询链后追加遍历逻辑即可:
users = User.arel_table posts = Post.arel_table result = User .left_joins(:posts) .select( users[Arel.star], posts[Arel.star].count.as("total_post_count") ) .group(users[:id]) .order(:total_post_count) .map do |user_record| { "user" => user_record, "total_post_count" => user_record.total_post_count } end
返回的result就是你要求的[{"user" => User实例, "total_post_count" => 10, ...}]结构。
方案2:使用pluck直接取原始值(性能更高,不需要完整对象功能时推荐)
pluck会直接返回数据库返回的原始值数组,跳过ActiveRecord实例的属性映射步骤:
users = User.arel_table posts = Post.arel_table result = User .left_joins(:posts) .group(users[:id]) .order("total_post_count") .pluck(users[Arel.star], posts[Arel.star].count.as("total_post_count")) .map do |user_attrs, total_count| # 如果不需要User实例,直接写 "user" => user_attrs 即可得到用户字段哈希 { "user" => User.new(user_attrs), "total_post_count" => total_count } end
方案3:使用select_all直接返回哈希(性能最高,完全跳过ActiveRecord对象实例化)
直接执行SQL得到原始哈希结果,适合大数据量查询场景:
users = User.arel_table posts = Post.arel_table arel = User .left_joins(:posts) .select( users[Arel.star], posts[Arel.star].count.as("total_post_count") ) .group(users[:id]) .order(:total_post_count) .arel raw_result = ActiveRecord::Base.connection.select_all(arel).to_a # 按需组装结构 result = raw_result.map do |row| user_attrs = row.slice(*User.column_names) { "user" => user_attrs, # 也可以转成User实例:User.new(user_attrs) "total_post_count" => row["total_post_count"] } end
内容的提问来源于stack exchange,提问作者Some Guy
相关产品推荐
相关产品推荐

