4

Is there a way to do the equivalent of ActiveRecord#find_each in DataMapper ?

(find_each will iterate over the result of a query by fetching things in memory by batch of 1000 rather than loading everything in memory)

mb14
  • 22,276
  • 7
  • 60
  • 102
  • 2
    No DM expert, but how does this look: https://github.com/postmodern/dm-chunked_query? – Michael Kohl Jan 13 '12 at 12:06
  • dm-chunked works perfectly. Thanks for the tip! BTW, you should have posted your comment as an answer, so the original poster can give you credit. You can still do so. – phatmann Sep 04 '12 at 19:00

2 Answers2

1

I checked dm-chunked_query as @MichaelKohl suggested, but I couldn't make it work as I'd expect, it gets the whole collection (I'd expect it to use OFFSET+LIMIT). So I wrote my own extension, it's pretty simple, hope it helps:

class DataMapper::Collection
  def batch(n)
    Enumerator.new do |y|
      offset = 0
      loop do 
        records = slice(offset, n)
        break if records.empty?
        records.each { |record| y.yield(record) }
        offset += records.size
      end
    end
  end
end

# Example
Model.all(:order => :id.asc).batch(1000).each { |obj| p obj }
tokland
  • 66,169
  • 13
  • 144
  • 170
0

I don't DM much, but it would not be that hard to write your own, assuming DM lets you apply your own 'limit'and 'offset' manually to queries.

Check out the implementation of find_each/find_in_batches in AR, only a couple dozen lines.

https://github.com/rails/rails/blob/master/activerecord/lib/active_record/relation/batches.rb#L19

https://github.com/rails/rails/blob/master/activerecord/lib/active_record/relation/batches.rb#L48

jrochkind
  • 22,799
  • 12
  • 59
  • 74
  • 1
    I'm sure I can write it, but I don't want to reinvent the wheel if there is already a way to do it. – mb14 Jan 13 '12 at 16:42