Пример #1
0
    def map_reduce(self, map, reduce, full_response=False, **kwargs):
        """Perform a map/reduce operation on this collection.

        If `full_response` is ``False`` (default) returns a
        :class:`~pymongo.collection.Collection` instance containing
        the results of the operation. Otherwise, returns the full
        response from the server to the `map reduce command`_.

        :Parameters:
          - `map`: map function (as a JavaScript string)
          - `reduce`: reduce function (as a JavaScript string)
          - `full_response` (optional): if ``True``, return full response to
            this command - otherwise just return the result collection
          - `**kwargs` (optional): additional arguments to the
            `map reduce command`_ may be passed as keyword arguments to this
            helper method, e.g.::

            >>> db.test.map_reduce(map, reduce, limit=2)

        .. note:: Requires server version **>= 1.1.1**

        .. seealso:: :doc:`/examples/map_reduce`

        .. versionadded:: 1.1.2+

        .. _map reduce command: http://www.mongodb.org/display/DOCS/MapReduce
        """
        command = SON([("mapreduce", self.__collection_name), ("map", map),
                       ("reduce", reduce)])
        command.update(**kwargs)

        response = self.__database._command(command)
        if full_response:
            return response
        return self.__database[response["result"]]
Пример #2
0
    def find_one(self,
                 spec_or_object_id=None,
                 fields=None,
                 slave_okay=None,
                 _sock=None,
                 _must_use_master=False):
        """Get a single object from the database.

        Raises TypeError if the argument is of an improper type. Returns a
        single SON object, or None if no result is found.

        :Parameters:
          - `spec_or_object_id` (optional): a SON object specifying elements
            which must be present for a document to be returned OR an instance
            of ObjectId to be used as the value for an _id query
          - `fields` (optional): a list of field names that should be included
            in the returned document ("_id" will always be included)
          - `slave_okay` (optional): DEPRECATED this option is deprecated and
            will be removed - see the slave_okay parameter to
            `pymongo.Connection.__init__`.
        """
        spec = spec_or_object_id
        if spec is None:
            spec = SON()
        if isinstance(spec, ObjectId):
            spec = SON({"_id": spec})

        for result in self.find(spec,
                                limit=-1,
                                fields=fields,
                                slave_okay=slave_okay,
                                _sock=_sock,
                                _must_use_master=_must_use_master):
            return result
        return None
Пример #3
0
    def map_reduce(self, map, reduce, full_response=False, **kwargs):
        """Perform a map/reduce operation on this collection.

        If `full_response` is ``False`` (default) returns a
        :class:`~pymongo.collection.Collection` instance containing
        the results of the operation. Otherwise, returns the full
        response from the server to the `map reduce command`_.

        :Parameters:
          - `map`: map function (as a JavaScript string)
          - `reduce`: reduce function (as a JavaScript string)
          - `full_response` (optional): if ``True``, return full response to
            this command - otherwise just return the result collection
          - `**kwargs` (optional): additional arguments to the
            `map reduce command`_ may be passed as keyword arguments to this
            helper method, e.g.::

            >>> db.test.map_reduce(map, reduce, limit=2)

        .. note:: Requires server version **>= 1.1.1**

        .. seealso:: :doc:`/examples/map_reduce`

        .. versionadded:: 1.2

        .. _map reduce command: http://www.mongodb.org/display/DOCS/MapReduce
        """
        command = SON([("mapreduce", self.__name),
                       ("map", map), ("reduce", reduce)])
        command.update(**kwargs)

        response = self.__database.command(command)
        if full_response:
            return response
        return self.__database[response["result"]]
Пример #4
0
 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
Пример #5
0
 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
Пример #6
0
    def __create(self, options):
        """Sends a create command with the given options.
        """

        # Send size as a float, not an int/long. BSON can only handle 32-bit
        # ints which conflicts w/ max collection size of 10000000000.
        if "size" in options:
            options["size"] = float(options["size"])

        command = SON({"create": self.__collection_name})
        command.update(options)

        self.__database._command(command)
Пример #7
0
    def __create(self, options):
        """Sends a create command with the given options.
        """

        # Send size as a float, not an int/long. BSON can only handle 32-bit
        # ints which conflicts w/ max collection size of 10000000000.
        if "size" in options:
            options["size"] = float(options["size"])

        command = SON({"create": self.__collection_name})
        command.update(options)

        self.__database._command(command)
Пример #8
0
    def authenticate(self, name, password):
        """Authenticate to use this database.

        Once authenticated, the user has full read and write access to this
        database. Raises TypeError if either name or password is not an
        instance of (str, unicode). Authentication lasts for the life of the
        database connection, or until `Database.logout` is called.

        The "admin" database is special. Authenticating on "admin" gives access
        to *all* databases. Effectively, "admin" access means root access to
        the database.

        :Parameters:
          - `name`: the name of the user to authenticate
          - `password`: the password of the user to authenticate
        """
        if not isinstance(name, types.StringTypes):
            raise TypeError("name must be an instance of (str, unicode)")
        if not isinstance(password, types.StringTypes):
            raise TypeError("password must be an instance of (str, unicode)")

        result = self._command({"getnonce": 1})
        nonce = result["nonce"]
        digest = self._password_digest(name, password)
        md5hash = _md5func()
        md5hash.update("%s%s%s" % (nonce, unicode(name), digest))
        key = unicode(md5hash.hexdigest())
        try:
            result = self._command(
                SON([("authenticate", 1), ("user", unicode(name)),
                     ("nonce", nonce), ("key", key)]))
            return True
        except OperationFailure:
            return False
Пример #9
0
    def rename(self, new_name):
        """Rename this collection.

        If operating in auth mode, client must be authorized as an admin to
        perform this operation. Raises TypeError if new_name is not an instance
        of (str, unicode). Raises InvalidName if new_name is not a valid
        collection name.

        :Parameters:
          - `new_name`: new name for this collection
        """
        if not isinstance(new_name, types.StringTypes):
            raise TypeError("new_name must be an instance of (str, unicode)")

        if not new_name or ".." in new_name:
            raise InvalidName("collection names cannot be empty")
        if "$" in new_name:
            raise InvalidName("collection names must not contain '$'")
        if new_name[0] == "." or new_name[-1] == ".":
            raise InvalidName("collecion names must not start or end with '.'")

        rename_command = SON([("renameCollection", self.full_name()),
                              ("to",
                               "%s.%s" % (self.__database.name(), new_name))])

        self.__database.connection().admin._command(rename_command)
Пример #10
0
    def count(self, with_limit_and_skip=False):
        """Get the size of the results set for this query.

        Returns the number of documents in the results set for this query. Does
        not take :meth:`limit` and :meth:`skip` into account by default - set
        `with_limit_and_skip` to ``True`` if that is the desired behavior.
        Raises :class:`~pymongo.errors.OperationFailure` on a database error.

        :Parameters:
          - `with_limit_and_skip` (optional): take any :meth:`limit` or
            :meth:`skip` that has been applied to this cursor into account when
            getting the count

        .. note:: The `with_limit_and_skip` parameter requires server
           version **>= 1.1.4-**

        .. versionadded:: 1.1.1
           The `with_limit_and_skip` parameter.
           :meth:`~pymongo.cursor.Cursor.__len__` was deprecated in favor of
           calling :meth:`count` with `with_limit_and_skip` set to ``True``.
        """
        command = SON([("count", self.__collection.name()),
                       ("query", self.__spec), ("fields", self.__fields)])

        if with_limit_and_skip:
            if self.__limit:
                command["limit"] = self.__limit
            if self.__skip:
                command["skip"] = self.__skip

        response = self.__collection.database()._command(
            command, ["ns missing"])
        if response.get("errmsg", "") == "ns missing":
            return 0
        return int(response["n"])
Пример #11
0
    def distinct(self, key):
        """Get a list of distinct values for `key` among all documents in the
        result set of this query.

        Raises :class:`TypeError` if `key` is not an instance of
        ``(str, unicode)``.

        :Parameters:
          - `key`: name of key for which we want to get the distinct values

        .. note:: Requires server version **>= 1.1.3+**

        .. seealso:: :meth:`pymongo.collection.Collection.distinct`

        .. versionadded:: 1.1.2+
        """
        if not isinstance(key, types.StringTypes):
            raise TypeError("key must be an instance of (str, unicode)")

        command = SON([("distinct", self.__collection.name()), ("key", key)])

        if self.__spec:
            command["query"] = self.__spec

        return self.__collection.database()._command(command)["values"]
Пример #12
0
    def drop_index(self, index_or_name):
        """Drops the specified index on this collection.

        Can be used on non-existant collections or collections with no indexes.
        Raises OperationFailure on an error. `index_or_name` can be either an
        index name (as returned by `create_index`), or an index specifier (as
        passed to `create_index`). An index specifier should be a list of (key,
        direction) pairs. Raises TypeError if index is not an instance of (str,
        unicode, list).

        :Parameters:
          - `index_or_name`: index (or name of index) to drop
        """
        name = index_or_name
        if isinstance(index_or_name, types.ListType):
            name = self._gen_index_name(index_or_name)

        if not isinstance(name, types.StringTypes):
            raise TypeError("index_or_name must be an index name or list")

        self.database().connection()._purge_index(self.database().name(),
                                                  self.name(), name)
        self.__database._command(
            SON([("deleteIndexes", self.__collection_name), ("index", name)]),
            ["ns not found"])
Пример #13
0
 def transform_value(value):
     if isinstance(value, DBRef):
         return self.__database.dereference(value)
     elif isinstance(value, types.ListType):
         return [transform_value(v) for v in value]
     elif isinstance(value, types.DictType):
         return transform_dict(SON(value))
     return value
Пример #14
0
 def transform_value(value):
     if isinstance(value, types.DictType):
         if "_id" in value and "_ns" in value:
             return DBRef(value["_ns"], transform_value(value["_id"]))
         else:
             return transform_dict(SON(value))
     elif isinstance(value, types.ListType):
         return [transform_value(v) for v in value]
     return value
Пример #15
0
    def transform_outgoing(self, son, collection):
        """Manipulate an outgoing SON object.

        :Parameters:
          - `son`: the SON object being retrieved from the database
          - `collection`: the collection this object was stored in
        """
        if self.will_copy():
            return SON(son)
        return son
Пример #16
0
    def transform_incoming(self, son, collection):
        """Manipulate an incoming SON object.

        :Parameters:
          - `son`: the SON object to be inserted into the database
          - `collection`: the collection the object is being inserted into
        """
        if self.will_copy():
            return SON(son)
        return son
Пример #17
0
    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
        return doc
Пример #18
0
 def __query_spec(self):
     """Get the spec to use for a query.
     """
     spec = SON({"query": self.__spec})
     if self.__ordering:
         spec["orderby"] = self.__ordering
     if self.__explain:
         spec["$explain"] = True
     if self.__hint:
         spec["$hint"] = self.__hint
     if self.__snapshot:
         spec["$snapshot"] = True
     return spec
Пример #19
0
    def count(self):
        """Get the size of the results set for this query.

        Returns the number of objects in the results set for this query. Does
        not take limit and skip into account. Raises OperationFailure on a
        database error.
        """
        command = SON([("count", self.__collection.name()),
                       ("query", self.__spec), ("fields", self.__fields)])
        response = self.__collection.database()._command(
            command, ["ns missing"])
        if response.get("errmsg", "") == "ns missing":
            return 0
        return int(response["n"])
Пример #20
0
    def find_one(self,
                 spec_or_object_id=None,
                 fields=None,
                 slave_okay=None,
                 _sock=None,
                 _must_use_master=False):
        """Get a single object from the database.

        Raises TypeError if the argument is of an improper type. Returns a
        single SON object, or None if no result is found.

        :Parameters:
          - `spec_or_object_id` (optional): a SON object specifying elements
            which must be present for a document to be returned OR an instance
            of ObjectId to be used as the value for an _id query
          - `fields` (optional): a list of field names that should be included
            in the returned document ("_id" will always be included)
          - `slave_okay` (optional): if True, this query should be allowed to
            execute on a slave (by default, certain queries are not allowed to
            execute on mongod instances running in slave mode). If slave_okay
            is set to None the Connection level default will be used - see the
            slave_okay parameter to `pymongo.Connection.__init__`.
        """
        spec = spec_or_object_id
        if spec is None:
            spec = SON()
        if isinstance(spec, ObjectId):
            spec = SON({"_id": spec})

        for result in self.find(spec,
                                limit=-1,
                                fields=fields,
                                slave_okay=slave_okay,
                                _sock=_sock,
                                _must_use_master=_must_use_master):
            return result
        return None
Пример #21
0
    def transform_outgoing(self, son, collection):
        """Replace DBRefs with embedded documents.
        """
        def transform_value(value):
            if isinstance(value, DBRef):
                return self.__database.dereference(value)
            elif isinstance(value, types.ListType):
                return [transform_value(v) for v in value]
            elif isinstance(value, types.DictType):
                return transform_dict(SON(value))
            return value

        def transform_dict(object):
            for (key, value) in object.items():
                object[key] = transform_value(value)
            return object

        return transform_dict(SON(son))
Пример #22
0
    def create_index(self, key_or_list, direction=None, unique=False, ttl=300):
        """Creates an index on this collection.

        Takes either a single key or a list of (key, direction) pairs.
        The key(s) must be an instance of ``(str, unicode)``, and the
        directions must be one of (:data:`~pymongo.ASCENDING`,
        :data:`~pymongo.DESCENDING`). Returns the name of the created
        index.

        :Parameters:
          - `key_or_list`: a single key or a list of (key, direction) pairs
            specifying the index to create
          - `direction` (optional): DEPRECATED this option will be removed
          - `unique` (optional): should this index guarantee uniqueness?
          - `ttl` (optional): time window (in seconds) during which this index
            will be recognized by subsequent calls to :meth:`ensure_index` -
            see documentation for :meth:`ensure_index` for details
        """
        if not isinstance(key_or_list, (str, unicode, list)):
            raise TypeError(
                "key_or_list must either be a single key or a list of (key, direction) pairs"
            )

        if direction is not None:
            warnings.warn(
                "specifying a direction for a single key index is "
                "deprecated and will be removed. there is no need "
                "for a direction on a single key index", DeprecationWarning)

        to_save = SON()
        keys = helpers._index_list(key_or_list)
        name = self._gen_index_name(keys)
        to_save["name"] = name
        to_save["ns"] = self.full_name()
        to_save["key"] = helpers._index_document(keys)
        to_save["unique"] = unique

        self.database().connection()._cache_index(self.__database.name(),
                                                  self.name(), name, ttl)

        self.database().system.indexes.insert(to_save,
                                              manipulate=False,
                                              check_keys=False)
        return to_save["name"]
Пример #23
0
    def transform_incoming(self, son, collection):
        """Replace embedded documents with DBRefs.
        """
        def transform_value(value):
            if isinstance(value, types.DictType):
                if "_id" in value and "_ns" in value:
                    return DBRef(value["_ns"], transform_value(value["_id"]))
                else:
                    return transform_dict(SON(value))
            elif isinstance(value, types.ListType):
                return [transform_value(v) for v in value]
            return value

        def transform_dict(object):
            for (key, value) in object.items():
                object[key] = transform_value(value)
            return object

        return transform_dict(SON(son))
Пример #24
0
    def __query_spec(self):
        """Get the spec to use for a query.

        Just `self.__spec`, unless this cursor needs special query fields, like
        orderby.
        """
        if not self.__ordering and not self.__explain and not self.__hint:
            return self.__spec

        spec = SON({"query": self.__spec})
        if self.__ordering:
            spec["orderby"] = self.__ordering
        if self.__explain:
            spec["$explain"] = True
        if self.__hint:
            spec["$hint"] = self.__hint
        if self.__snapshot:
            spec["$snapshot"] = True
        return spec
Пример #25
0
    def remove(self, spec_or_object_id):
        """Remove an object(s) from this collection.

        Raises TypeEror if the argument is not an instance of
        (dict, ObjectId).

        :Parameters:
          - `spec_or_object_id` (optional): a SON object specifying elements
            which must be present for a document to be removed OR an instance
            of ObjectId to be used as the value for an _id element
        """
        spec = spec_or_object_id
        if isinstance(spec, ObjectId):
            spec = SON({"_id": spec})

        if not isinstance(spec, types.DictType):
            raise TypeError("spec must be an instance of dict, not %s" %
                            type(spec))

        self._send_message(2006, _ZERO + bson.BSON.from_dict(spec))
Пример #26
0
def _index_document(index_list):
    """Helper to generate an index specifying document.

    Takes a list of (key, direction) pairs.
    """
    if not isinstance(index_list, list):
        raise TypeError("if no direction is specified, key_or_list must be an "
                        "instance of list")
    if not len(index_list):
        raise ValueError("key_or_list must not be the empty list")

    index = SON()
    for (key, value) in index_list:
        if not isinstance(key, (str, unicode)):
            raise TypeError("first item in each key pair must be a string")
        if not isinstance(value, int):
            raise TypeError(
                "second item in each key pair must be ASCENDING or "
                "DESCENDING")
        index[key] = value
    return index
Пример #27
0
    def eval(self, code, *args):
        """Evaluate a JavaScript expression on the Mongo server.

        Useful if you need to touch a lot of data lightly; in such a scenario
        the network transfer of the data could be a bottleneck. The `code`
        argument must be a JavaScript function. Additional positional
        arguments will be passed to that function when it is run on the
        server.

        Raises TypeError if `code` is not an instance of (str, unicode,
        `Code`). Raises OperationFailure if the eval fails. Returns the result
        of the evaluation.

        :Parameters:
          - `code`: string representation of JavaScript code to be evaluated
          - `args` (optional): additional positional arguments are passed to
            the `code` being evaluated
        """
        if not isinstance(code, Code):
            code = Code(code)

        command = SON([("$eval", code), ("args", list(args))])
        result = self._command(command)
        return result.get("retval", None)
Пример #28
0
def _element_to_bson(key, value, check_keys):
    if not isinstance(key, (str, unicode)):
        raise InvalidDocument(
            "documents must have only string keys, key was %r" % key)

    if check_keys:
        if key.startswith("$"):
            raise InvalidName("key %r must not start with '$'" % key)
        if "." in key:
            raise InvalidName("key %r must not contain '.'" % key)

    name = _make_c_string(key)
    if isinstance(value, float):
        return "\x01" + name + struct.pack("<d", value)

    # Use Binary w/ subtype 3 for UUID instances
    try:
        import uuid

        if isinstance(value, uuid.UUID):
            value = Binary(value.bytes, subtype=3)
    except ImportError:
        pass

    if isinstance(value, Binary):
        subtype = value.subtype
        if subtype == 2:
            value = struct.pack("<i", len(value)) + value
        return "\x05%s%s%s%s" % (name, struct.pack(
            "<i", len(value)), chr(subtype), value)
    if isinstance(value, Code):
        cstring = _make_c_string(value)
        scope = _dict_to_bson(value.scope, False)
        full_length = struct.pack("<i", 8 + len(cstring) + len(scope))
        length = struct.pack("<i", len(cstring))
        return "\x0F" + name + full_length + length + cstring + scope
    if isinstance(value, str):
        cstring = _make_c_string(value)
        length = struct.pack("<i", len(cstring))
        return "\x02" + name + length + cstring
    if isinstance(value, unicode):
        cstring = _make_c_string(value)
        length = struct.pack("<i", len(cstring))
        return "\x02" + name + length + cstring
    if isinstance(value, dict):
        return "\x03" + name + _dict_to_bson(value, check_keys)
    if isinstance(value, (list, tuple)):
        as_dict = SON(zip([str(i) for i in range(len(value))], value))
        return "\x04" + name + _dict_to_bson(as_dict, check_keys)
    if isinstance(value, ObjectId):
        return "\x07" + name + value.binary
    if value is True:
        return "\x08" + name + "\x01"
    if value is False:
        return "\x08" + name + "\x00"
    if isinstance(value, (int, long)):
        # TODO this is a really ugly way to check for this...
        if value > 2**64 / 2 - 1 or value < -2**64 / 2:
            raise OverflowError("MongoDB can only handle up to 8-byte ints")
        if value > 2**32 / 2 - 1 or value < -2**32 / 2:
            return "\x12" + name + struct.pack("<q", value)
        return "\x10" + name + struct.pack("<i", value)
    if isinstance(value, datetime.datetime):
        millis = int(
            calendar.timegm(value.timetuple()) * 1000 +
            value.microsecond / 1000)
        return "\x09" + name + struct.pack("<q", millis)
    if value is None:
        return "\x0A" + name
    if isinstance(value, _RE_TYPE):
        pattern = value.pattern
        flags = ""
        if value.flags & re.IGNORECASE:
            flags += "i"
        if value.flags & re.LOCALE:
            flags += "l"
        if value.flags & re.MULTILINE:
            flags += "m"
        if value.flags & re.DOTALL:
            flags += "s"
        if value.flags & re.UNICODE:
            flags += "u"
        if value.flags & re.VERBOSE:
            flags += "x"
        return "\x0B" + name + _make_c_string(pattern) + _make_c_string(flags)
    if isinstance(value, DBRef):
        return _element_to_bson(key, value.as_doc(), False)

    raise InvalidDocument("cannot convert value of type %s to bson" %
                          type(value))
Пример #29
0
    def find(self,
             spec=None,
             fields=None,
             skip=0,
             limit=0,
             slave_okay=None,
             timeout=True,
             snapshot=False,
             _sock=None,
             _must_use_master=False):
        """Query the database.

        The `spec` argument is a prototype document that all results must
        match. For example:

        >>> db.test.find({"hello": "world"})

        only matches documents that have a key "hello" with value "world".
        Matches can have other keys *in addition* to "hello". The `fields`
        argument is used to specify a subset of fields that should be included
        in the result documents. By limiting results to a certain subset of
        fields you can cut down on network traffic and decoding time.

        Raises TypeError if any of the arguments are of improper type. Returns
        an instance of Cursor corresponding to this query.

        :Parameters:
          - `spec` (optional): a SON object specifying elements which must be
            present for a document to be included in the result set
          - `fields` (optional): a list of field names that should be returned
            in the result set ("_id" will always be included)
          - `skip` (optional): the number of documents to omit (from the start
            of the result set) when returning the results
          - `limit` (optional): the maximum number of results to return
          - `slave_okay` (optional): if True, this query should be allowed to
            execute on a slave (by default, certain queries are not allowed to
            execute on mongod instances running in slave mode). If slave_okay
            is set to None the Connection level default will be used - see the
            slave_okay parameter to `pymongo.Connection.__init__`.
          - `timeout` (optional): if True, any returned cursor will be subject
            to the normal timeout behavior of the mongod process. Otherwise,
            the returned cursor will never timeout at the server. Care should
            be taken to ensure that cursors with timeout turned off are
            properly closed.
          - `snapshot` (optional): if True, snapshot mode will be used for this
            query. Snapshot mode assures no duplicates are returned, or objects
            missed, which were present at both the start and end of the query's
            execution. For details, see the wiki_

        .. _wiki: http://www.mongodb.org/display/DOCS/How+to+do+Snapshotting+in+the+Mongo+Database
        """
        if spec is None:
            spec = SON()
        if slave_okay is None:
            slave_okay = self.__database.connection().slave_okay
        if not isinstance(spec, types.DictType):
            raise TypeError("spec must be an instance of dict")
        if not isinstance(fields, (types.ListType, types.NoneType)):
            raise TypeError("fields must be an instance of list")
        if not isinstance(skip, types.IntType):
            raise TypeError("skip must be an instance of int")
        if not isinstance(limit, types.IntType):
            raise TypeError("limit must be an instance of int")
        if not isinstance(slave_okay, types.BooleanType):
            raise TypeError("slave_okay must be an instance of bool")
        if not isinstance(timeout, types.BooleanType):
            raise TypeError("timeout must be an instance of bool")
        if not isinstance(snapshot, types.BooleanType):
            raise TypeError("snapshot must be an instance of bool")

        if fields is not None:
            if not fields:
                fields = ["_id"]
            fields = self._fields_list_to_dict(fields)

        return Cursor(self,
                      spec,
                      fields,
                      skip,
                      limit,
                      slave_okay,
                      timeout,
                      snapshot,
                      _sock=_sock,
                      _must_use_master=_must_use_master)