def hint(self, index): """Adds a 'hint', telling Mongo the proper index to use for the query. Judicious use of hints can greatly improve query performance. When doing a query on multiple fields (at least one of which is indexed) pass the indexed field as a hint to the query. Hinting will not do anything if the corresponding index does not exist. Raises :class:`~pymongo.errors.InvalidOperation` if this cursor has already been used. `index` should be an index as passed to :meth:`~pymongo.collection.Collection.create_index` (e.g. ``[('field', ASCENDING)]``). If `index` is ``None`` any existing hints for this query are cleared. The last hint applied to this cursor takes precedence over all others. :Parameters: - `index`: index to hint on (as an index specifier) """ self.__check_okay_to_chain() if index is None: self.__hint = None return self self.__hint = helpers._index_document(index) return self
def sort(self, key_or_list, direction=None): """Sorts this cursor's results. Takes either a single key and a direction, or a list of (key, direction) pairs. The key(s) must be an instance of ``(str, unicode)``, and the direction(s) must be one of (:data:`~pymongo.ASCENDING`, :data:`~pymongo.DESCENDING`). Raises :class:`~pymongo.errors.InvalidOperation` if this cursor has already been used. Only the last :meth:`sort` applied to this cursor has any effect. :Parameters: - `key_or_list`: a single key or a list of (key, direction) pairs specifying the keys to sort on - `direction` (optional): only used if `key_or_list` is a single key, if not given :data:`~pymongo.ASCENDING` is assumed """ self.__check_okay_to_chain() keys = helpers._index_list(key_or_list, direction) self.__ordering = helpers._index_document(keys) return self
def __init__(self, collection, spec=None, fields=None, skip=0, limit=0, timeout=True, snapshot=False, tailable=False, sort=None, max_scan=None, as_class=None, slave_okay=False, await_data=False, partial=False, manipulate=True, read_preference=ReadPreference.PRIMARY, tag_sets=[{}], secondary_acceptable_latency_ms=None, exhaust=False, _must_use_master=False, _uuid_subtype=None, _first_batch=None, _cursor_id=None, **kwargs): """Create a new cursor. Should not be called directly by application developers - see :meth:`~pymongo.collection.Collection.find` instead. .. mongodoc:: cursors """ self.__id = _cursor_id self.__is_command_cursor = _cursor_id is not None if spec is None: spec = {} if not isinstance(spec, dict): raise TypeError("spec must be an instance of dict") if not isinstance(skip, int): raise TypeError("skip must be an instance of int") if not isinstance(limit, int): raise TypeError("limit must be an instance of int") if not isinstance(timeout, bool): raise TypeError("timeout must be an instance of bool") if not isinstance(snapshot, bool): raise TypeError("snapshot must be an instance of bool") if not isinstance(tailable, bool): raise TypeError("tailable must be an instance of bool") if not isinstance(slave_okay, bool): raise TypeError("slave_okay must be an instance of bool") if not isinstance(await_data, bool): raise TypeError("await_data must be an instance of bool") if not isinstance(partial, bool): raise TypeError("partial must be an instance of bool") if not isinstance(exhaust, bool): raise TypeError("exhaust must be an instance of bool") if fields is not None: if not fields: fields = {"_id": 1} if not isinstance(fields, dict): fields = helpers._fields_list_to_dict(fields) if as_class is None: as_class = collection.database.connection.document_class self.__collection = collection self.__spec = spec self.__fields = fields self.__skip = skip self.__limit = limit self.__batch_size = 0 # Exhaust cursor support if self.__collection.database.connection.is_mongos and exhaust: raise InvalidOperation('Exhaust cursors are ' 'not supported by mongos') if limit and exhaust: raise InvalidOperation("Can't use limit and exhaust together.") self.__exhaust = exhaust self.__exhaust_mgr = None # This is ugly. People want to be able to do cursor[5:5] and # get an empty result set (old behavior was an # exception). It's hard to do that right, though, because the # server uses limit(0) to mean 'no limit'. So we set __empty # in that case and check for it when iterating. We also unset # it anytime we change __limit. self.__empty = False self.__snapshot = snapshot self.__ordering = sort and helpers._index_document(sort) or None self.__max_scan = max_scan self.__explain = False self.__hint = None self.__as_class = as_class self.__slave_okay = slave_okay self.__manipulate = manipulate self.__read_preference = read_preference self.__tag_sets = tag_sets self.__secondary_acceptable_latency_ms = secondary_acceptable_latency_ms self.__tz_aware = collection.database.connection.tz_aware self.__must_use_master = _must_use_master self.__uuid_subtype = _uuid_subtype or collection.uuid_subtype self.__data = deque(_first_batch or []) self.__connection_id = None self.__retrieved = 0 self.__killed = False self.__query_flags = 0 if tailable: self.__query_flags |= _QUERY_OPTIONS["tailable_cursor"] if not timeout: self.__query_flags |= _QUERY_OPTIONS["no_timeout"] if tailable and await_data: self.__query_flags |= _QUERY_OPTIONS["await_data"] if exhaust: self.__query_flags |= _QUERY_OPTIONS["exhaust"] if partial: self.__query_flags |= _QUERY_OPTIONS["partial"] # this is for passing network_timeout through if it's specified # need to use kwargs as None is a legit value for network_timeout self.__kwargs = kwargs