Skip to content

Instantly share code, notes, and snippets.

@krasnoukhov
Created December 13, 2012 21:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save krasnoukhov/4280326 to your computer and use it in GitHub Desktop.
Save krasnoukhov/4280326 to your computer and use it in GitHub Desktop.
Mongoid extension used for iteration through MongoDB collection using ranges. Useful when iteration performing asynchronously. Works much faster then skip/limit queries.
module Mongoid
class Criteria
def range_by(by = 1000, &block)
raise ArgumentError, "Please specify correct range" unless by.to_i > 0
first = klass.order_by(:_id.asc).first.id.generation_time
pages = (klass.count.to_f/by.to_i).ceil
frame = (
(klass.order_by(:_id.asc).last.id.generation_time - first + 1).to_f /
pages
).ceil
pages.times { |x|
yield clone, gt: (first + x*frame).to_i, lt: (first + (x+1)*frame).to_i
}
end
def range_with(range)
range.stringify_keys!
clone.where(
:_id.gte => BSON::ObjectId.from_time(Time.at(range["gt"])).to_s,
:_id.lt => BSON::ObjectId.from_time(Time.at(range["lt"])).to_s
)
end
end
end
Post.all.range_by(500) { |criteria, range|
# Immediatly find objects
puts criteria.range_with(range).count
# Or pass range hash to some async worker
# Hash format: {:gt=>1355431169, :lt=>1355431170}
PostWorker.perform_async(range)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment