ActiveRecord:避免在查询响应中实例化对象



在进行查询时,有没有直接的方法可以避免实例化对象?

我想得到一个散列数组,而不是一个没有实例化阶段的ActiveRecord对象数组,以提高性能。

现在,我这样做:

sql = User.where(name: 'John', ...).to_sql
ActiveRecord::Base.connection.execute(sql).to_a

有没有像User.where(name: 'John', ...).skip_instantiation.to_a这样的神奇方法?

要将SQL结果映射到哈希数组中,可以使用OpenStruct类。

require 'ostruct'
query = "SELECT * FROM USERS"
results = ActiveRecord::Base.connection.execute(query)
mapped = results.map {|r| OpenStruct.new(r)}

请参阅https://ruby-doc.org/stdlib-2.0.0/libdoc/ostruct/rdoc/OpenStruct.html

拔毛怎么样https://guides.rubyonrails.org/active_record_querying.html#pluck

Customer.where(code: ["Bob01", "Fred01"]).pluck(:id, :code, :name)
#    (0.4ms)  SELECT "customers"."id", "customers"."code", "customers"."name" FROM "customers" WHERE "customers"."code" IN ($1, $2)  [["code", "Bob01"], ["code", "Fred01"]]
# => [[1, "Bob01", "Bob Bobson"], [2, "Fred01", "Fred Fredson"]]

如果你想要一个散列数组,那么关于呢

columns = [:id, :code, :name]
Customer.
where(code: ["Bob01", "Fred01"]).
pluck(*columns).
map {|row| columns.zip(row).to_h }
# => [{:id=>1, :code=>"Bob01", :name=>"Bob Bobson"}, {:id=>2, :code=>"Fred01", :name=>"Fred Fredson"}]

是的,使用.pluck,正如Ben Stephens概述的那样。

然而,我想更详细地介绍一些可能还不够的情况。

情况1,如果我想从联接表的列中提取数据,该怎么办
A:易于使用的字符串参数:

User.where(name: 'John', ...).joins(:posts).pluck(:id, "#{Post.table_name}.message")

案例2,如果我想提取任意SQL,例如,从JSONB列中的哈希中提取一个值,该怎么办
答:有点复杂。首先,.pluck不支持任意SQL,因此您必须使用.select。第二,重要的是为任意的";列";用CCD_ 6 SQL语句选择。第三,要跳过AR对象的实例化,请像其他人建议的那样使用ActiveRecord::Base.connection.execute。把它放在一起:

sql = User.where(name: 'John', ...).select(:id, "(metadata->'age')::integer AS age").to_sql
ActiveRecord::Base.connection.execute(sql).to_a
#=> [{"id" => 1, "age" => 28}]  

我已将此方法添加到ActiveRecord::Relation类:

# config/initializers/active_record_relation.rb
ActiveRecord::Relation.class_eval do
def run_sql
ActiveRecord::Base.connection.execute(to_sql).to_a
end
end

现在我可以在不实例化对象的情况下运行查询:

User.select('name as custom_name').run_sql

相关内容

  • 没有找到相关文章

最新更新