You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让ActiveRecord原生查询的member_ids返回整数数组而非字符串?

问题:如何让PostgreSQL查询返回的member_ids直接为整数数组(无需Ruby端循环解析)

原查询代码

@tags = ActiveRecord::Base.connection.execute(
  <<~SQL
    SELECT t.id, t.name, t.member_tags_count, (
      SELECT
        json_agg(mt.member_id) as member_ids
      FROM member_tags mt
      WHERE mt.tag_id = t.id)
    FROM tags t
    ORDER BY LOWER(t.name)
  SQL
)

render json: @tags

原查询结果

该查询耗时1.9ms,返回结果示例:

#<PG::Result:0x000000010e368580 status=PGRES_TUPLES_OK ntuples=31 nfields=4 cmd_tuples=31>
(ruby) @tags.first
{"id"=>1, "name"=>"Avengers", "member_tags_count"=>3, "member_ids"=>"[1, 3, 7]"}

核心问题

API要求member_ids为整数数组,但当前返回的是字符串格式的JSON数组,希望无需循环@tags执行JSON.parse,直接让member_ids以数组形式返回。

当前临时方案(耗时较高)

以下方案返回正确格式,但耗时是原查询的4倍(5.7ms),代码繁琐:

@tags = Tag
  .joins(:member_tags)
  .order('LOWER(name)')
  .group(:id)
  .pluck(
    :id,
    :name,
    :member_tags_count,
    'array_agg(member_tags.member_id)'
  ).map do |column| {
    id: column[0],
    name: column[1],
    member_tags_count: column[2],
    member_ids: column[3]
  }
end

render json: @tags

返回结果示例:

(ruby) @tags.first
{:id=>1, :name=>"Avengers", :member_tags_count=>3, :member_ids=>[1, 3, 7]}

优化方案(保持原查询耗时)

直接修改原SQL中的聚合函数,将json_agg替换为array_agg,PostgreSQL会返回原生数组类型,ActiveRecord的PG适配器会自动将其解析为Ruby整数数组,无需Ruby端额外处理:

@tags = ActiveRecord::Base.connection.execute(
  <<~SQL
    SELECT t.id, t.name, t.member_tags_count, (
      SELECT
        array_agg(mt.member_id) as member_ids
      FROM member_tags mt
      WHERE mt.tag_id = t.id)
    FROM tags t
    ORDER BY LOWER(t.name)
  SQL
)

render json: @tags

效果说明

  • 耗时仍保持1.9ms左右,和原查询效率一致
  • 返回结果中member_ids直接为整数数组:
    (ruby) @tags.first
    {"id"=>1, "name"=>"Avengers", "member_tags_count"=>3, "member_ids"=>[1, 3, 7]}
    

原理

json_agg返回的是JSON格式的字符串,PG::Result会默认按字符串处理;而array_agg返回的是PostgreSQL原生整数数组类型,ActiveRecord会自动映射为Ruby的Array<Integer>类型,直接满足API的格式要求。

内容的提问来源于stack exchange,提问作者Coderama

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 06:40:52