是否可以在Rails / ActiveRecord中运行find_by_sql查询而不将所有结果加载到内存中?

时间:2010-10-25 19:50:36

标签: ruby-on-rails ruby activerecord

我正在构建一个Rails插件,可以从Rails应用程序中提取大量数据。它动态构建跨多个表的查询,并返回大量结果。以下是一个用于从Spree(Rails购物车)中提取购买数据的查询示例:

select orders.user_id as from_id, variants.product_id as to_id from orders, line_items, variants where orders.user_id is not null and variants.product_id is not null and orders.id = line_items.order_id and line_items.variant_id = variants.id order by from_id;

问题是ActiveRecord将所有结果加载到内存中。有没有办法避免这种情况而不是编写特定于DB的代码? (我知道find_each,但这不允许排序。)

3 个答案:

答案 0 :(得分:2)

这绝对是可能的,这是一篇介绍它的文章:

http://www.rubyinside.com/paginate_by_sql-rails-pagination-on-your-own-sql-queries-50.html

他们有可以逐字复制的代码,但关键是使用SQL的count方法。使用此代码,您可以拨打paginate_by_sql而不是find_by_sql,然后传入页面和每页参数。

答案 1 :(得分:0)

也许您还想查看Rails ActiveRecord批处理,以较小的块检索记录:

http://guides.rubyonrails.org/active_record_querying.html#retrieving-multiple-objects-in-batches

答案 2 :(得分:0)

Jaime的回答让我沿着一条更高效的查询路径登陆will_paginate,提供了一个paginate_by_sql方法。经过几十年的努力,每个都包含在一个分页的SQL中:

def paginated_sql_each(query, &block)
  page = 1
  begin
    results = paginate_by_sql(query, :page => page)
    results.each { |r| block.call(r) }
    page += 1
  end while !results.empty?
end