2008-09-12 06:14:34 +02:00
|
|
|
module CouchRest
|
2008-09-12 06:09:39 +02:00
|
|
|
class Streamer
|
|
|
|
attr_accessor :db
|
|
|
|
def initialize db
|
|
|
|
@db = db
|
|
|
|
end
|
|
|
|
|
2008-09-30 08:39:57 +02:00
|
|
|
# Stream a view, yielding one row at a time. Shells out to <tt>curl</tt> to keep RAM usage low when you have millions of rows.
|
2008-10-14 10:07:48 +02:00
|
|
|
def view name, params = nil, &block
|
2009-10-08 12:27:22 +02:00
|
|
|
urlst = if /^_/.match(name) then
|
|
|
|
"#{@db.root}/#{name}"
|
|
|
|
else
|
|
|
|
name = name.split('/')
|
|
|
|
dname = name.shift
|
|
|
|
vname = name.join('/')
|
|
|
|
"#{@db.root}/_design/#{dname}/_view/#{vname}"
|
|
|
|
end
|
2008-09-12 06:09:39 +02:00
|
|
|
url = CouchRest.paramify_url urlst, params
|
2008-10-15 00:08:17 +02:00
|
|
|
# puts "stream #{url}"
|
2008-10-14 10:07:48 +02:00
|
|
|
first = nil
|
2009-10-08 12:27:22 +02:00
|
|
|
IO.popen("curl --silent \"#{url}\"") do |view|
|
2008-10-14 10:07:48 +02:00
|
|
|
first = view.gets # discard header
|
|
|
|
while line = view.gets
|
|
|
|
row = parse_line(line)
|
2009-10-08 12:27:22 +02:00
|
|
|
block.call row unless row.nil? # last line "}]" discarded
|
2008-09-12 06:09:39 +02:00
|
|
|
end
|
|
|
|
end
|
2008-10-15 00:08:17 +02:00
|
|
|
parse_first(first)
|
2008-09-12 06:09:39 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
def parse_line line
|
|
|
|
return nil unless line
|
|
|
|
if /(\{.*\}),?/.match(line.chomp)
|
|
|
|
JSON.parse($1)
|
|
|
|
end
|
|
|
|
end
|
2008-10-15 00:08:17 +02:00
|
|
|
|
|
|
|
def parse_first first
|
|
|
|
return nil unless first
|
|
|
|
parts = first.split(',')
|
|
|
|
parts.pop
|
|
|
|
line = parts.join(',')
|
|
|
|
JSON.parse("#{line}}")
|
|
|
|
rescue
|
|
|
|
nil
|
|
|
|
end
|
2008-09-12 06:09:39 +02:00
|
|
|
|
|
|
|
end
|
2009-10-08 12:27:22 +02:00
|
|
|
end
|