def __last_error(namespace, args): """Data to send to do a lastError. """ cmd = SON([("getlasterror", 1)]) cmd.update(args) splitns = namespace.split('.', 1) return query(0, splitns[0] + '.$cmd', 0, -1, cmd)
def __last_error(namespace, args): """Data to send to do a lastError. """ cmd = SON([("getlasterror", 1)]) cmd.update(args) splitns = namespace.split('.', 1) return query(0, splitns[0] + '.$cmd', 0, -1, cmd)
def transform_incoming(self, son, collection): """Move _id to the front if it's there. """ if not "_id" in son: return son transformed = SON({"_id": son["_id"]}) transformed.update(son) return transformed
def transform_incoming(self, son, collection): """Move _id to the front if it's there. """ if not "_id" in son: return son transformed = SON({"_id": son["_id"]}) transformed.update(son) return transformed
def as_doc(self): """Get the SON document representation of this DBRef. Generally not needed by application developers """ doc = SON([("$ref", self.collection), ("$id", self.id)]) if self.database is not None: doc["$db"] = self.database doc.update(self.__kwargs) return doc
def __query_spec(self): """Get the spec to use for a query. """ operators = {} if self.__ordering: operators["$orderby"] = self.__ordering if self.__explain: operators["$explain"] = True if self.__hint: operators["$hint"] = self.__hint if self.__snapshot: operators["$snapshot"] = True if self.__max_scan: operators["$maxScan"] = self.__max_scan # Only set $readPreference if it's something other than # PRIMARY to avoid problems with mongos versions that # don't support read preferences. if (self.__collection.database.connection.is_mongos and self.__read_preference != ReadPreference.PRIMARY): has_tags = self.__tag_sets and self.__tag_sets != [{}] # For maximum backwards compatibility, don't set $readPreference # for SECONDARY_PREFERRED unless tags are in use. Just rely on # the slaveOkay bit (set automatically if read preference is not # PRIMARY), which has the same behavior. if (self.__read_preference != ReadPreference.SECONDARY_PREFERRED or has_tags): read_pref = { 'mode': read_preferences.mongos_mode(self.__read_preference) } if has_tags: read_pref['tags'] = self.__tag_sets operators['$readPreference'] = read_pref if operators: # Make a shallow copy so we can cleanly rewind or clone. spec = self.__spec.copy() # Only commands that can be run on secondaries should have any # operators added to the spec. Command queries can be issued # by db.command or calling find_one on $cmd directly if self.collection.name == "$cmd": # Don't change commands that can't be sent to secondaries command_name = spec and list(spec.keys())[0].lower() or "" if command_name not in secondary_ok_commands: return spec elif command_name == 'mapreduce': # mapreduce shouldn't be changed if its not inline out = spec.get('out') if not isinstance(out, dict) or not out.get('inline'): return spec # White-listed commands must be wrapped in $query. if "$query" not in spec: # $query has to come first spec = SON([("$query", spec)]) if not isinstance(spec, SON): # Ensure the spec is SON. As order is important this will # ensure its set before merging in any extra operators. spec = SON(spec) spec.update(operators) return spec # Have to wrap with $query if "query" is the first key. # We can't just use $query anytime "query" is a key as # that breaks commands like count and find_and_modify. # Checking spec.keys()[0] covers the case that the spec # was passed as an instance of SON or OrderedDict. elif ( "query" in self.__spec and (len(self.__spec) == 1 or list(self.__spec.keys())[0] == "query")): return SON({"$query": self.__spec}) return self.__spec
def __query_spec(self): """Get the spec to use for a query. """ operators = {} if self.__ordering: operators["$orderby"] = self.__ordering if self.__explain: operators["$explain"] = True if self.__hint: operators["$hint"] = self.__hint if self.__snapshot: operators["$snapshot"] = True if self.__max_scan: operators["$maxScan"] = self.__max_scan # Only set $readPreference if it's something other than # PRIMARY to avoid problems with mongos versions that # don't support read preferences. if (self.__collection.database.connection.is_mongos and self.__read_preference != ReadPreference.PRIMARY): has_tags = self.__tag_sets and self.__tag_sets != [{}] # For maximum backwards compatibility, don't set $readPreference # for SECONDARY_PREFERRED unless tags are in use. Just rely on # the slaveOkay bit (set automatically if read preference is not # PRIMARY), which has the same behavior. if (self.__read_preference != ReadPreference.SECONDARY_PREFERRED or has_tags): read_pref = { 'mode': read_preferences.mongos_mode(self.__read_preference) } if has_tags: read_pref['tags'] = self.__tag_sets operators['$readPreference'] = read_pref if operators: # Make a shallow copy so we can cleanly rewind or clone. spec = self.__spec.copy() # Only commands that can be run on secondaries should have any # operators added to the spec. Command queries can be issued # by db.command or calling find_one on $cmd directly if self.collection.name == "$cmd": # Don't change commands that can't be sent to secondaries command_name = spec and list(spec.keys())[0].lower() or "" if command_name not in secondary_ok_commands: return spec elif command_name == 'mapreduce': # mapreduce shouldn't be changed if its not inline out = spec.get('out') if not isinstance(out, dict) or not out.get('inline'): return spec # White-listed commands must be wrapped in $query. if "$query" not in spec: # $query has to come first spec = SON([("$query", spec)]) if not isinstance(spec, SON): # Ensure the spec is SON. As order is important this will # ensure its set before merging in any extra operators. spec = SON(spec) spec.update(operators) return spec # Have to wrap with $query if "query" is the first key. # We can't just use $query anytime "query" is a key as # that breaks commands like count and find_and_modify. # Checking spec.keys()[0] covers the case that the spec # was passed as an instance of SON or OrderedDict. elif ("query" in self.__spec and (len(self.__spec) == 1 or list(self.__spec.keys())[0] == "query")): return SON({"$query": self.__spec}) return self.__spec
def command(self, command, value=1, check=True, allowable_errors=[], uuid_subtype=OLD_UUID_SUBTYPE, **kwargs): """Issue a MongoDB command. Send command `command` to the database and return the response. If `command` is an instance of :class:`basestring` (:class:`str` in python 3) then the command {`command`: `value`} will be sent. Otherwise, `command` must be an instance of :class:`dict` and will be sent as is. Any additional keyword arguments will be added to the final command document before it is sent. For example, a command like ``{buildinfo: 1}`` can be sent using: >>> db.command("buildinfo") For a command where the value matters, like ``{collstats: collection_name}`` we can do: >>> db.command("collstats", collection_name) For commands that take additional arguments we can use kwargs. So ``{filemd5: object_id, root: file_root}`` becomes: >>> db.command("filemd5", object_id, root=file_root) :Parameters: - `command`: document representing the command to be issued, or the name of the command (for simple commands only). .. note:: the order of keys in the `command` document is significant (the "verb" must come first), so commands which require multiple keys (e.g. `findandmodify`) should use an instance of :class:`~bson.son.SON` or a string and kwargs instead of a Python `dict`. - `value` (optional): value to use for the command verb when `command` is passed as a string - `check` (optional): check the response for errors, raising :class:`~pymongo.errors.OperationFailure` if there are any - `allowable_errors`: if `check` is ``True``, error messages in this list will be ignored by error-checking - `uuid_subtype` (optional): The BSON binary subtype to use for a UUID used in this command. - `read_preference`: The read preference for this connection. See :class:`~pymongo.read_preferences.ReadPreference` for available options. - `tag_sets`: Read from replica-set members with these tags. To specify a priority-order for tag sets, provide a list of tag sets: ``[{'dc': 'ny'}, {'dc': 'la'}, {}]``. A final, empty tag set, ``{}``, means "read from any member that matches the mode, ignoring tags." ReplicaSetConnection tries each set of tags in turn until it finds a set of tags with at least one matching member. - `secondary_acceptable_latency_ms`: Any replica-set member whose ping time is within secondary_acceptable_latency_ms of the nearest member may accept reads. Default 15 milliseconds. **Ignored by mongos** and must be configured on the command line. See the localThreshold_ option for more information. - `**kwargs` (optional): additional keyword arguments will be added to the command document before it is sent .. note:: ``command`` ignores the ``network_timeout`` parameter. .. versionchanged:: 2.3 Added `tag_sets` and `secondary_acceptable_latency_ms` options. .. versionchanged:: 2.2 Added support for `as_class` - the class you want to use for the resulting documents .. versionchanged:: 1.6 Added the `value` argument for string commands, and keyword arguments for additional command options. .. versionchanged:: 1.5 `command` can be a string in addition to a full document. .. versionadded:: 1.4 .. mongodoc:: commands .. _localThreshold: http://docs.mongodb.org/manual/reference/mongos/#cmdoption-mongos--localThreshold """ if isinstance(command, str): command = SON([(command, value)]) command_name = list(command.keys())[0].lower() must_use_master = kwargs.pop('_use_master', False) if command_name not in rp.secondary_ok_commands: must_use_master = True # Special-case: mapreduce can go to secondaries only if inline if command_name == 'mapreduce': out = command.get('out') or kwargs.get('out') if not isinstance(out, dict) or not out.get('inline'): must_use_master = True extra_opts = { 'as_class': kwargs.pop('as_class', None), 'slave_okay': kwargs.pop('slave_okay', self.slave_okay), '_must_use_master': must_use_master, '_uuid_subtype': uuid_subtype } extra_opts['read_preference'] = kwargs.pop( 'read_preference', self.read_preference) extra_opts['tag_sets'] = kwargs.pop( 'tag_sets', self.tag_sets) extra_opts['secondary_acceptable_latency_ms'] = kwargs.pop( 'secondary_acceptable_latency_ms', self.secondary_acceptable_latency_ms) fields = kwargs.get('fields') if fields is not None and not isinstance(fields, dict): kwargs['fields'] = helpers._fields_list_to_dict(fields) command.update(kwargs) result = self["$cmd"].find_one(command, **extra_opts) if check: msg = "command %s failed: %%s" % repr(command).replace("%", "%%") helpers._check_command_response(result, self.connection.disconnect, msg, allowable_errors) return result
def command(self, command, value=1, check=True, allowable_errors=[], uuid_subtype=OLD_UUID_SUBTYPE, **kwargs): """Issue a MongoDB command. Send command `command` to the database and return the response. If `command` is an instance of :class:`basestring` (:class:`str` in python 3) then the command {`command`: `value`} will be sent. Otherwise, `command` must be an instance of :class:`dict` and will be sent as is. Any additional keyword arguments will be added to the final command document before it is sent. For example, a command like ``{buildinfo: 1}`` can be sent using: >>> db.command("buildinfo") For a command where the value matters, like ``{collstats: collection_name}`` we can do: >>> db.command("collstats", collection_name) For commands that take additional arguments we can use kwargs. So ``{filemd5: object_id, root: file_root}`` becomes: >>> db.command("filemd5", object_id, root=file_root) :Parameters: - `command`: document representing the command to be issued, or the name of the command (for simple commands only). .. note:: the order of keys in the `command` document is significant (the "verb" must come first), so commands which require multiple keys (e.g. `findandmodify`) should use an instance of :class:`~bson.son.SON` or a string and kwargs instead of a Python `dict`. - `value` (optional): value to use for the command verb when `command` is passed as a string - `check` (optional): check the response for errors, raising :class:`~pymongo.errors.OperationFailure` if there are any - `allowable_errors`: if `check` is ``True``, error messages in this list will be ignored by error-checking - `uuid_subtype` (optional): The BSON binary subtype to use for a UUID used in this command. - `read_preference`: The read preference for this connection. See :class:`~pymongo.read_preferences.ReadPreference` for available options. - `tag_sets`: Read from replica-set members with these tags. To specify a priority-order for tag sets, provide a list of tag sets: ``[{'dc': 'ny'}, {'dc': 'la'}, {}]``. A final, empty tag set, ``{}``, means "read from any member that matches the mode, ignoring tags." ReplicaSetConnection tries each set of tags in turn until it finds a set of tags with at least one matching member. - `secondary_acceptable_latency_ms`: Any replica-set member whose ping time is within secondary_acceptable_latency_ms of the nearest member may accept reads. Default 15 milliseconds. **Ignored by mongos** and must be configured on the command line. See the localThreshold_ option for more information. - `**kwargs` (optional): additional keyword arguments will be added to the command document before it is sent .. note:: ``command`` ignores the ``network_timeout`` parameter. .. versionchanged:: 2.3 Added `tag_sets` and `secondary_acceptable_latency_ms` options. .. versionchanged:: 2.2 Added support for `as_class` - the class you want to use for the resulting documents .. versionchanged:: 1.6 Added the `value` argument for string commands, and keyword arguments for additional command options. .. versionchanged:: 1.5 `command` can be a string in addition to a full document. .. versionadded:: 1.4 .. mongodoc:: commands .. _localThreshold: http://docs.mongodb.org/manual/reference/mongos/#cmdoption-mongos--localThreshold """ if isinstance(command, str): command = SON([(command, value)]) command_name = list(command.keys())[0].lower() must_use_master = kwargs.pop('_use_master', False) if command_name not in rp.secondary_ok_commands: must_use_master = True # Special-case: mapreduce can go to secondaries only if inline if command_name == 'mapreduce': out = command.get('out') or kwargs.get('out') if not isinstance(out, dict) or not out.get('inline'): must_use_master = True extra_opts = { 'as_class': kwargs.pop('as_class', None), 'slave_okay': kwargs.pop('slave_okay', self.slave_okay), '_must_use_master': must_use_master, '_uuid_subtype': uuid_subtype } extra_opts['read_preference'] = kwargs.pop('read_preference', self.read_preference) extra_opts['tag_sets'] = kwargs.pop('tag_sets', self.tag_sets) extra_opts['secondary_acceptable_latency_ms'] = kwargs.pop( 'secondary_acceptable_latency_ms', self.secondary_acceptable_latency_ms) fields = kwargs.get('fields') if fields is not None and not isinstance(fields, dict): kwargs['fields'] = helpers._fields_list_to_dict(fields) command.update(kwargs) result = self["$cmd"].find_one(command, **extra_opts) if check: msg = "command %s failed: %%s" % repr(command).replace("%", "%%") helpers._check_command_response(result, self.connection.disconnect, msg, allowable_errors) return result