125 lines
No EOL
3.2 KiB
Ruby
125 lines
No EOL
3.2 KiB
Ruby
module Enumerable
|
|
def group_by
|
|
inject({}) do |grouped, element|
|
|
(grouped[yield(element)] ||= []) << element
|
|
grouped
|
|
end
|
|
end unless [].respond_to?(:group_by)
|
|
|
|
def group_by_fast
|
|
inject({}) do |grouped, element|
|
|
(grouped[yield(element)] ||= []) << element
|
|
grouped
|
|
end
|
|
end
|
|
end
|
|
|
|
class CouchRest
|
|
class Pager
|
|
attr_accessor :db
|
|
def initialize db
|
|
@db = db
|
|
end
|
|
|
|
def all_docs(count=100, &block)
|
|
startkey = nil
|
|
oldend = nil
|
|
|
|
while docrows = request_all_docs(count+1, startkey)
|
|
startkey = docrows.last['key']
|
|
docrows.pop if docrows.length > count
|
|
if oldend == startkey
|
|
break
|
|
end
|
|
yield(docrows)
|
|
oldend = startkey
|
|
end
|
|
end
|
|
|
|
def key_reduce(view, count, firstkey = nil, lastkey = nil, &block)
|
|
# start with no keys
|
|
startkey = firstkey
|
|
# lastprocessedkey = nil
|
|
keepgoing = true
|
|
|
|
while keepgoing && viewrows = request_view(view, count, startkey)
|
|
startkey = viewrows.first['key']
|
|
endkey = viewrows.last['key']
|
|
|
|
if (startkey == endkey)
|
|
# we need to rerequest to get a bigger page
|
|
# so we know we have all the rows for that key
|
|
viewrows = @db.view(view, :key => startkey)['rows']
|
|
# we need to do an offset thing to find the next startkey
|
|
# otherwise we just get stuck
|
|
lastdocid = viewrows.last['id']
|
|
fornextloop = @db.view(view, :startkey => startkey, :startkey_docid => lastdocid, :count => 2)['rows']
|
|
|
|
newendkey = fornextloop.last['key']
|
|
if (newendkey == endkey)
|
|
keepgoing = false
|
|
else
|
|
startkey = newendkey
|
|
end
|
|
rows = viewrows
|
|
else
|
|
rows = []
|
|
for r in viewrows
|
|
if (lastkey && r['key'] == lastkey)
|
|
keepgoing = false
|
|
break
|
|
end
|
|
break if (r['key'] == endkey)
|
|
rows << r
|
|
end
|
|
startkey = endkey
|
|
end
|
|
|
|
# grouped = rows.group_by{|r|r['key']}
|
|
# grouped.each do |k, rs|
|
|
# vs = rs.collect{|r|r['value']}
|
|
# yield(k,vs)
|
|
# end
|
|
|
|
key = :begin
|
|
values = []
|
|
|
|
rows.each do |r|
|
|
if key != r['key']
|
|
# we're on a new key, yield the old first and then reset
|
|
yield(key, values) if key != :begin
|
|
key = r['key']
|
|
values = []
|
|
end
|
|
# keep accumulating
|
|
values << r['value']
|
|
end
|
|
yield(key, values)
|
|
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def request_all_docs count, startkey = nil
|
|
opts = {}
|
|
opts[:count] = count if count
|
|
opts[:startkey] = startkey if startkey
|
|
results = @db.documents(opts)
|
|
rows = results['rows']
|
|
rows unless rows.length == 0
|
|
end
|
|
|
|
def request_view view, count = nil, startkey = nil, endkey = nil
|
|
opts = {}
|
|
opts[:count] = count if count
|
|
opts[:startkey] = startkey if startkey
|
|
opts[:endkey] = endkey if endkey
|
|
|
|
results = @db.view(view, opts)
|
|
rows = results['rows']
|
|
rows unless rows.length == 0
|
|
end
|
|
|
|
end
|
|
end |