postgresql 如何将ActiveRecord::Base.connection.execute集合ID(has_many)转换为数组而不是字符串

icomxhvb  于 2022-11-23  发布在  PostgreSQL
关注(0)|答案(2)|浏览(120)

这是我在控制器中的查询(索引操作):

@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]"}

问题:member_ids应该是API的整数数组,但它当前作为字符串返回。
**问题:**有没有办法将member_ids作为数组返回,而不将@tags结果循环到JSON.parse

下面是我当前的实现,这样我就可以继续了,但是它看起来很混乱,运行时间要长4倍(5.7毫秒)。

@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]}
h22fl7wq

h22fl7wq1#

您需要json_agg,而不是Postgres驱动程序知道如何处理的array_agg

query = Tag
  .joins(:member_tags)
  .order(Tag.arel_table[:name].lower)
  .group(:id)
  .select(
    :id,
    :name,
    :member_tags_count,
    Arel::Nodes::NamedFunction.new(
      'json_agg', 
      [MemberTag.arel_table[:member_id]]
    ).as('member_ids')
  )
@tags = Tag.connection.select_all(query.arel).map(&:to_h)

使用.pluck代替.select_all也没有什么意义,因为它迫使您不得不经历处理数组的混乱。

whlutmcx

whlutmcx2#

您可以使用as_json方法,并将pluck更改为带有id数组别名的select

@tags = Tag
  .joins(:member_tags)
  .order('LOWER(name)')
  .group(:id)
  .select(
    :id,
    :name,
    :member_tags_count,
    'array_agg(member_tags.member_id) AS member_ids'
  ).as_json

render json: @tags

相关问题