在进行查询时,有没有直接的方法可以避免实例化对象?
我想得到一个散列数组,而不是一个没有实例化阶段的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