Class | Mongo::Cursor |
In: |
lib/mongo/cursor.rb
|
Parent: | Object |
A cursor over query results. Returned objects are hashes.
collection | [R] | |
cursor_id | [R] | |
fields | [R] | |
full_collection_name | [R] | |
hint | [R] | |
options | [R] | |
order | [R] | |
selector | [R] | |
show_disk_loc | [R] | |
snapshot | [R] | |
timeout | [R] | |
transformer | [R] |
Create a new cursor.
Note: cursors are created when executing queries using [Collection#find] and other similar methods. Application developers shouldn‘t have to create cursors manually.
@return [Cursor]
@core cursors constructor_details
# File lib/mongo/cursor.rb, line 39 def initialize(collection, opts={}) @cursor_id = nil @db = collection.db @collection = collection @connection = @db.connection @logger = @connection.logger # Query selector @selector = opts[:selector] || {} # Special operators that form part of $query @order = opts[:order] @explain = opts[:explain] @hint = opts[:hint] @snapshot = opts[:snapshot] @max_scan = opts.fetch(:max_scan, nil) @return_key = opts.fetch(:return_key, nil) @show_disk_loc = opts.fetch(:show_disk_loc, nil) # Wire-protocol settings @fields = convert_fields_for_query(opts[:fields]) @skip = opts[:skip] || 0 @limit = opts[:limit] || 0 @tailable = opts[:tailable] || false @timeout = opts.fetch(:timeout, true) @options = 0 # Use this socket for the query @socket = opts[:socket] @closed = false @query_run = false @transformer = opts[:transformer] if value = opts[:read] Mongo::Support.validate_read_preference(value) else value = collection.read_preference end @read_preference = value.is_a?(Hash) ? value.dup : value batch_size(opts[:batch_size] || 0) @full_collection_name = "#{@collection.db.name}.#{@collection.name}" @cache = [] @returned = 0 if(!@timeout) add_option(OP_QUERY_NO_CURSOR_TIMEOUT) end if(@read_preference != :primary) add_option(OP_QUERY_SLAVE_OK) end if(@tailable) add_option(OP_QUERY_TAILABLE) end if @collection.name =~ /^\$cmd/ || @collection.name =~ /^system/ @command = true else @command = false end @checkin_read_pool = false @checkin_connection = false @read_pool = nil end
Add an option to the query options bitfield.
@param opt a valid query option
@raise InvalidOperation if this method is run after the cursor has bee
iterated for the first time.
@return [Integer] the current value of the options bitfield for this cursor.
@see www.mongodb.org/display/DOCS/Mongo+Wire+Protocol#MongoWireProtocol-Mongo::Constants::OPQUERY
# File lib/mongo/cursor.rb, line 376 def add_option(opt) check_modifiable @options |= opt @options end
Guess whether the cursor is alive on the server.
Note that this method only checks whether we have a cursor id. The cursor may still have timed out on the server. This will be indicated in the next call to Cursor#next.
@return [Boolean]
# File lib/mongo/cursor.rb, line 115 def alive? @cursor_id && @cursor_id != 0 end
Set the batch size for server responses.
Note that the batch size will take effect only on queries where the number to be returned is greater than 100.
@param [Integer] size either 0 or some integer greater than 1. If 0,
the server will determine the batch size.
@return [Cursor]
# File lib/mongo/cursor.rb, line 266 def batch_size(size=nil) return @batch_size unless size check_modifiable if size < 0 || size == 1 raise ArgumentError, "Invalid value for batch_size #{size}; must be 0 or > 1." else @batch_size = @limit != 0 && size > @limit ? @limit : size end self end
Close the cursor.
Note: if a cursor is read until exhausted (read until Mongo::Constants::OP_QUERY or Mongo::Constants::OP_GETMORE returns zero for the cursor id), there is no need to close it manually.
Note also: Collection#find takes an optional block argument which can be used to ensure that your cursors get closed.
@return [True]
# File lib/mongo/cursor.rb, line 335 def close if @cursor_id && @cursor_id != 0 message = BSON::ByteBuffer.new([0, 0, 0, 0]) message.put_int(1) message.put_long(@cursor_id) log(:debug, "Cursor#close #{@cursor_id}") @connection.send_message(Mongo::Constants::OP_KILL_CURSORS, message, :connection => :reader) end @cursor_id = 0 @closed = true end
Get the size of the result set for this query.
@param [Boolean] whether of not to take notice of skip and limit
@return [Integer] the number of objects in the result set for this query.
@raise [OperationFailure] on a database error.
# File lib/mongo/cursor.rb, line 181 def count(skip_and_limit = false) command = BSON::OrderedHash["count", @collection.name, "query", @selector] if skip_and_limit command.merge!(BSON::OrderedHash["limit", @limit]) if @limit != 0 command.merge!(BSON::OrderedHash["skip", @skip]) if @skip != 0 end command.merge!(BSON::OrderedHash["fields", @fields]) response = @db.command(command) return response['n'].to_i if Mongo::Support.ok?(response) return 0 if response['errmsg'] == "ns missing" raise OperationFailure.new("Count failed: #{response['errmsg']}", response['code'], response) end
Iterate over each document in this cursor, yielding it to the given block.
Iterating over an entire cursor will close it.
@yield passes each document to a block for processing.
@example if ‘comments’ represents a collection of comments:
comments.find.each do |doc| puts doc['user'] end
# File lib/mongo/cursor.rb, line 289 def each while doc = self.next yield doc end end
Get the explain plan for this cursor.
@return [Hash] a document containing the explain plan for this cursor.
@core explain explain-instance_method
# File lib/mongo/cursor.rb, line 316 def explain c = Cursor.new(@collection, query_options_hash.merge(:limit => -@limit.abs, :explain => true)) explanation = c.next_document c.close explanation end
Determine whether this cursor has any remaining results.
@return [Boolean]
# File lib/mongo/cursor.rb, line 170 def has_next? num_remaining > 0 end
Limit the number of results to be returned by this cursor.
This method overrides any limit specified in the Collection#find method, and only the last limit applied has an effect.
@return [Integer] the current number_to_return if no parameter is given.
@raise [InvalidOperation] if this cursor has already been used.
@core limit limit-instance_method
# File lib/mongo/cursor.rb, line 232 def limit(number_to_return=nil) return @limit unless number_to_return check_modifiable @limit = number_to_return self end
Get the next document specified the cursor options.
@return [Hash, Nil] the next document or Nil if no documents remain.
# File lib/mongo/cursor.rb, line 122 def next if @cache.length == 0 if @query_run && (@options & OP_QUERY_EXHAUST != 0) close return nil else refresh end end doc = @cache.shift if doc && doc['$err'] err = doc['$err'] # If the server has stopped being the master (e.g., it's one of a # pair but it has died or something like that) then we close that # connection. The next request will re-open on master server. if err.include?("not master") @connection.close raise ConnectionFailure.new(err, doc['code'], doc) end raise OperationFailure.new(err, doc['code'], doc) end if @transformer.nil? doc else @transformer.call(doc) if doc end end
Get the query options for this Cursor.
@return [Hash]
# File lib/mongo/cursor.rb, line 403 def query_options_hash { :selector => @selector, :fields => @fields, :skip => @skip, :limit => @limit, :order => @order, :hint => @hint, :snapshot => @snapshot, :timeout => @timeout, :max_scan => @max_scan, :return_key => @return_key, :show_disk_loc => @show_disk_loc } end
Returns an integer indicating which query options have been selected.
@return [Integer]
@see www.mongodb.org/display/DOCS/Mongo+Wire+Protocol#MongoWireProtocol-Mongo::Constants::OPQUERY The MongoDB wire protocol.
# File lib/mongo/cursor.rb, line 360 def query_opts warn "The method Cursor#query_opts has been deprecated " + "and will removed in v2.0. Use Cursor#options instead." @options end
Remove an option from the query options bitfield.
@param opt a valid query option
@raise InvalidOperation if this method is run after the cursor has bee
iterated for the first time.
@return [Integer] the current value of the options bitfield for this cursor.
@see www.mongodb.org/display/DOCS/Mongo+Wire+Protocol#MongoWireProtocol-Mongo::Constants::OPQUERY
# File lib/mongo/cursor.rb, line 393 def remove_option(opt) check_modifiable @options &= ~opt @options end
Skips the first number_to_skip results of this cursor. Returns the current number_to_skip if no parameter is given.
This method overrides any skip specified in the Collection#find method, and only the last skip applied has an effect.
@return [Integer]
@raise [InvalidOperation] if this cursor has already been used.
# File lib/mongo/cursor.rb, line 249 def skip(number_to_skip=nil) return @skip unless number_to_skip check_modifiable @skip = number_to_skip self end
Sort this cursor‘s results.
This method overrides any sort order specified in the Collection#find method, and only the last sort applied has an effect.
@param [Symbol, Array] key_or_list either 1) a key to sort by or 2)
an array of [key, direction] pairs to sort by. Direction should be specified as Mongo::ASCENDING (or :ascending / :asc) or Mongo::DESCENDING (or :descending / :desc)
@raise [InvalidOperation] if this cursor has already been used.
@raise [InvalidSortValueError] if the specified order is invalid.
# File lib/mongo/cursor.rb, line 209 def sort(key_or_list, direction=nil) check_modifiable if !direction.nil? order = [[key_or_list, direction]] else order = key_or_list end @order = order self end
Receive all the documents from this cursor as an array of hashes.
Notes:
If you‘ve already started iterating over the cursor, the array returned by this method contains only the remaining documents. See Cursor#rewind! if you need to reset the cursor.
Use of this method is discouraged - in most cases, it‘s much more efficient to retrieve documents as you need them by iterating over the cursor.
@return [Array] an array of documents.
# File lib/mongo/cursor.rb, line 307 def to_a super end