def find_and_modify(self, query={}, update=None, upsert=False, **kwargs):
        def wrapper(result):
            no_obj_error = "No matching object found"
            if not result['ok']:
                if result["errmsg"] == no_obj_error:
                    return None
                else:
                    raise ValueError("Unexpected Error: %s" % (result, ))
            return result.get('value')

        if (not update and not kwargs.get('remove', None)):
            raise ValueError("Must either update or remove")

        if (update and kwargs.get('remove', None)):
            raise ValueError("Can't do both update and remove")

        cmd = SON([("findAndModify", self._collection_name)])
        cmd.update(kwargs)
        # No need to include empty args
        if query:
            cmd['query'] = query
        if update:
            cmd['update'] = update
        if upsert:
            cmd['upsert'] = upsert

        no_obj_error = "No matching object found"

        d = self._database["$cmd"].find_one(cmd)
        d.addCallback(wrapper)

        return d
Beispiel #2
0
    def find(self, spec=None, skip=0, limit=0, fields=None, filter=None, _proto=None):
        if spec is None:
            spec = SON()

        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 istance 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 fields is not None:
            if not fields:
                fields = ["_id"]
            fields = self._fields_list_to_dict(fields)

        if isinstance(filter, (qf.sort, qf.hint, qf.explain, qf.snapshot)):
            spec = SON(dict(query=spec))
            for k, v in filter.items():
                spec[k] = isinstance(v, types.TupleType) and SON(v) or v

        # send the command through a specific connection
        # this is required for the connection pool to work
        # when safe=True
        if _proto is None:
            proto = self._database._connection
        else:
            proto = _proto
        return proto.OP_QUERY(str(self), spec, skip, limit, fields)
    def find_and_modify(self, query={}, update=None, upsert=False, **kwargs):
        def wrapper(result):
            no_obj_error = "No matching object found"
            if not result['ok']:
                if result["errmsg"] == no_obj_error:
                    return None
                else:
                    raise ValueError("Unexpected Error: %s" % (result,))
            return result.get('value')

        if (not update and not kwargs.get('remove', None)):
            raise ValueError("Must either update or remove")

        if (update and kwargs.get('remove', None)):
            raise ValueError("Can't do both update and remove")

        cmd = SON([("findAndModify", self._collection_name)])
        cmd.update(kwargs)
        # No need to include empty args
        if query:
            cmd['query'] = query
        if update:
            cmd['update'] = update
        if upsert:
            cmd['upsert'] = upsert

        no_obj_error = "No matching object found"

        d = self._database["$cmd"].find_one(cmd)
        d.addCallback(wrapper)

        return d
 def findAndModify(self, query={}, update=None, upsert=False, **kwargs):
     '''@see: http://api.mongodb.org/python/1.10.1%2B/api/pymongo/collection.html#pymongo.collection.Collection.find_and_modify'''
     cmd = SON([("findAndModify", self._collection_name),
                ("query", query),
                ("update", update),
                ("upsert", upsert), ])
     cmd.update(**kwargs)
     d = self._database["$cmd"].find_one(cmd)
     return d
Beispiel #5
0
def aggregate(self, pipeline):
    if not isinstance(pipeline, (dict, list, tuple)):
        raise TypeError("pipeline must be a dict, list or tuple")

    if isinstance(pipeline, dict):
        pipeline = [pipeline]

    command = SON([("aggregate", self._collection_name)])
    command.update({"pipeline": pipeline})

    return self._database["$cmd"].find_one(command)
Beispiel #6
0
 def findAndModify(self, query={}, update=None, upsert=False, **kwargs):
     '''@see: http://api.mongodb.org/python/1.10.1%2B/api/pymongo/collection.html#pymongo.collection.Collection.find_and_modify'''
     cmd = SON([
         ("findAndModify", self._collection_name),
         ("query", query),
         ("update", update),
         ("upsert", upsert),
     ])
     cmd.update(**kwargs)
     d = self._database["$cmd"].find_one(cmd)
     return d
 def command(self, command, value=1, **kwargs):
     '''
     @see: http://www.mongodb.org/display/DOCS/Commands
     @see: http://api.mongodb.org/python/1.10.1%2B/api/pymongo/database.html#pymongo.database.Database.command
     '''
     
     if isinstance(command, basestring):
         command = SON([(command, value)])
     command.update(kwargs)
     d = self["$cmd"].find_one(command)
     return d
    def map_reduce(self, map, reduce, full_response=False, **kwargs):
        def wrapper(result, full_response):
            if full_response:
                return result
            return result.get("result")

        cmd = SON([("mapreduce", self._collection_name), ("map", map), ("reduce", reduce)])
        cmd.update(**kwargs)
        d = self._database["$cmd"].find_one(cmd)
        d.addCallback(wrapper, full_response)
        return d
 def runCommand(self, command, value=1, **kwargs):
     '''
     @see: http://www.mongodb.org/display/DOCS/Commands
     @deprecated: use database.command() instead, as in pymongo
     http://api.mongodb.org/python/1.10.1%2B/api/pymongo/database.html#pymongo.database.Database.command
     '''
     warnings.warn("collection.runCommand: use database.command() instead", DeprecationWarning)
     cmd = SON([ (command, value) ])
     cmd.update(**kwargs)
     d = self._database["$cmd"].find_one(cmd)
     return d
Beispiel #10
0
 def runCommand(self, command, value=1, **kwargs):
     '''
     @see: http://www.mongodb.org/display/DOCS/Commands
     @deprecated: use database.command() instead, as in pymongo
     http://api.mongodb.org/python/1.10.1%2B/api/pymongo/database.html#pymongo.database.Database.command
     '''
     warnings.warn("collection.runCommand: use database.command() instead",
                   DeprecationWarning)
     cmd = SON([(command, value)])
     cmd.update(**kwargs)
     d = self._database["$cmd"].find_one(cmd)
     return d
Beispiel #11
0
    def map_reduce(self, map, reduce, full_response=False, **kwargs):
        def wrapper(result, full_response):
            if full_response:
                return result
            return result.get("result")

        cmd = SON([("mapreduce", self._collection_name), ("map", map),
                   ("reduce", reduce)])
        cmd.update(**kwargs)
        d = self._database["$cmd"].find_one(cmd)
        d.addCallback(wrapper, full_response)
        return d
Beispiel #12
0
    def count(self, spec=None, fields=None):
        def wrapper(result):
            return result["n"]

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

        spec = SON([("count", self._collection_name), ("query", spec or SON()),
                    ("fields", fields)])
        d = self._database["$cmd"].find_one(spec)
        d.addCallback(wrapper)
        return d
    def create_index(self, sort_fields, **kwargs):
        def wrapper(result, name):
            return name

        if not isinstance(sort_fields, qf.sort):
            raise TypeError("sort_fields must be an instance of filter.sort")

        if "name" not in kwargs:
            name = self._gen_index_name(sort_fields["orderby"])
        else:
            name = kwargs.pop("name")

        key = SON()
        for k,v in sort_fields["orderby"]:
            key.update({k:v})

        index = SON(dict(
          ns=str(self),
          name=name,
          key=key
        ))

        if "drop_dups" in kwargs:
            kwargs["dropDups"] = kwargs.pop("drop_dups")

        if "bucket_size" in kwargs:
            kwargs["bucketSize"] = kwargs.pop("bucket_size")
        
        index.update(kwargs)
        d = self._database.system.indexes.insert(index, safe=True)
        d.addCallback(wrapper, name)
        return d
Beispiel #14
0
 def filemd5(self, spec):
     if not isinstance(spec, ObjectId):
         raise ValueError(
             "filemd5 expected an objectid for its on-keyword argument")
     spec = SON([("filemd5", spec), ("root", self._collection_name)])
     doc = yield self._database['$cmd'].find_one(spec)
     defer.returnValue((doc or {}).get('md5'))
Beispiel #15
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
Beispiel #16
0
    def create_index(self, sort_fields, unique=False, dropDups=False):
        def wrapper(result, name):
            return name

        if not isinstance(sort_fields, qf.sort):
            raise TypeError("sort_fields must be an instance of filter.sort")

        name = self._gen_index_name(sort_fields["orderby"])
        index = SON(
            dict(ns=str(self),
                 name=name,
                 key=SON(dict(sort_fields["orderby"])),
                 unique=unique,
                 dropDups=dropDups))

        d = self._database.system.indexes.insert(index, safe=True)
        d.addCallback(wrapper, name)
        return d
Beispiel #17
0
    def remove(self, spec, safe=False):
        if isinstance(spec, ObjectId):
            spec = SON(dict(_id=spec))
        if not isinstance(spec, types.DictType):
            raise TypeError("spec must be an instance of dict, not %s" % type(spec))

        proto = self._database._connection
        proto.OP_DELETE(str(self), spec)
        return self.__safe_operation(proto, safe)
Beispiel #18
0
    def drop_index(self, index_identifier):
        if isinstance(index_identifier, types.StringTypes):
            name = index_identifier
        elif isinstance(index_identifier, qf.sort):
            name = self._gen_index_name(index_identifier["orderby"])
        else:
            raise TypeError("index_identifier must be a name or instance of filter.sort")

        cmd = SON([("deleteIndexes", self._collection_name), ("index", name)])
        return self._database["$cmd"].find_one(cmd)
    def test_index_haystack(self):
        db = self.db
        coll = self.coll
        yield coll.drop_indexes()

        _id = yield coll.insert({
            "pos": {
                "long": 34.2,
                "lat": 33.3
            },
            "type": "restaurant"
        })
        yield coll.insert({
            "pos": {
                "long": 34.2,
                "lat": 37.3
            },
            "type": "restaurant"
        })
        yield coll.insert({
            "pos": {
                "long": 59.1,
                "lat": 87.2
            },
            "type": "office"
        })

        yield coll.create_index(
            filter.sort(filter.GEOHAYSTACK("pos") + filter.ASCENDING("type")),
            **{'bucket_size': 1})

        # TODO: A db.command method has not been implemented yet.
        # Sending command directly
        command = SON([
            ("geoSearch", "mycol"),
            ("near", [33, 33]),
            ("maxDistance", 6),
            ("search", {
                "type": "restaurant"
            }),
            ("limit", 30),
        ])

        results = yield db["$cmd"].find_one(command)
        self.assertEqual(2, len(results['results']))
        self.assertEqual(
            {
                "_id": _id,
                "pos": {
                    "long": 34.2,
                    "lat": 33.3
                },
                "type": "restaurant"
            }, results["results"][0])
    def create_index(self, sort_fields, **kwargs):
        def wrapper(result, name):
            return name

        if not isinstance(sort_fields, qf.sort):
            raise TypeError("sort_fields must be an instance of filter.sort")

        if "name" not in kwargs:
            name = self._gen_index_name(sort_fields["orderby"])
        else:
            name = kwargs.pop("name")

        key = SON()
        for k,v in sort_fields["orderby"]:
            key.update({k:v})

        index = SON(dict(
          ns=str(self),
          name=name,
          key=key
        ))

        if "drop_dups" in kwargs:
            kwargs["dropDups"] = kwargs.pop("drop_dups")

        if "bucket_size" in kwargs:
            kwargs["bucketSize"] = kwargs.pop("bucket_size")
        
        index.update(kwargs)
        d = self._database.system.indexes.insert(index, safe=True)
        d.addCallback(wrapper, name)
        return d
    def filemd5(self, spec):
        def wrapper(result):
            return result.get('md5')

        if not isinstance(spec, ObjectId):
            raise ValueError(
                "filemd5 expected an objectid for its on-keyword argument")

        spec = SON([("filemd5", spec), ("root", self._collection_name)])

        d = self._database['$cmd'].find_one(spec)
        d.addCallback(wrapper)
        return d
    def create_collection(self, name, options={}):
        def wrapper(result, deferred, collection):
            if result.get("ok", 0.0):
                deferred.callback(collection)
            else:
                deferred.errback(RuntimeError(result.get("errmsg", "unknown error")))
                
        deferred = defer.Deferred()
        collection = Collection(self, name)

        if options:
            if "size" in options:
                options["size"] = float(options["size"])

            command = SON({"create": name})
            command.update(options)
            d = self["$cmd"].find_one(command)
            d.addCallback(wrapper, deferred, collection)
        else:
            deferred.callback(collection)

        return deferred
    def authenticate_with_nonce(self, result, name, password, d):
        nonce = result['nonce']
        key = helpers._auth_key(nonce, name, password)

        # hacky because order matters
        auth_command = SON(authenticate=1)
        auth_command['user'] = unicode(name)
        auth_command['nonce'] = nonce
        auth_command['key'] = key

        # Now actually authenticate
        self["$cmd"].find_one(auth_command).addCallback(
            self.authenticated, d).addErrback(d.errback)
    def create_collection(self, name, options={}):
        def wrapper(result, deferred, collection):
            if result.get("ok", 0.0):
                deferred.callback(collection)
            else:
                deferred.errback(RuntimeError(result.get("errmsg", "unknown error")))

        deferred = defer.Deferred()
        collection = Collection(self, name)

        if options:
            if "size" in options:
                options["size"] = float(options["size"])

            command = SON({"create": name})
            command.update(options)
            d = self["$cmd"].find_one(command)
            d.addCallback(wrapper, deferred, collection)
        else:
            deferred.callback(collection)

        return deferred
Beispiel #25
0
    def distinct(self, key, spec=None):
        def wrapper(result):
            if result:
                return result.get("values")
            return {}

        cmd = SON([("distinct", self._collection_name), ("key", key)])
        if spec:
            cmd["query"] = spec

        d = self._database["$cmd"].find_one(cmd)
        d.addCallback(wrapper)
        return d
Beispiel #26
0
    def _authenticate_with_nonce(self, result, name, password, d):
        nonce = result['nonce']
        key = helpers._auth_key(nonce, name, password)

        # hacky because order matters
        auth_command = SON(authenticate=1)
        auth_command['user'] = unicode(name)
        auth_command['nonce'] = nonce
        auth_command['key'] = key

        # Now actually authenticate
        Collection(self.database,
                   "$cmd").find_one(auth_command, _proto=self).addCallback(
                       self._authenticated, d).addErrback(self._auth_error, d)
Beispiel #27
0
    def find_one(self, spec=None, fields=None, _proto=None):
        def wrapper(docs):
            doc = docs and docs[0] or {}
            if doc.get("err") is not None:
                raise errors.OperationFailure(doc)
            else:
                return doc

        if isinstance(spec, ObjectId):
            spec = SON(dict(_id=spec))

        d = self.find(spec, limit=-1, fields=fields, _proto=_proto)
        d.addCallback(wrapper)
        return d
    def checkMaster(self, deferred):
        try:
            c = self.connection()
            if isinstance(
                    c, _offline
            ):  # don't bother trying to check for master if not connected
                return
            cursor = yield c.OP_QUERY("admin.$cmd", SON([('isMaster', 1)]), 0,
                                      -1)
            results = yield cursor.as_list()
            info = results and results[0] or {}
            self.isMaster = info.get('ismaster', False)
            if 'hosts' in info:
                self.manager.updateHosts(info['hosts'])

            deferred.callback(self.isMaster)
        except:
            reactor.callLater(1, self.checkMaster, deferred)
    def append(self, conn):
        if not self._checkedMaster:
            self._checkedMaster = True
            cursor = yield conn.OP_QUERY("admin.$cmd", SON([('isMaster', 1)]),
                                         0, -1)
            info = yield cursor.as_list()
            info = info and info[0] or {}
            self.isMaster = info.get('ismaster', False)

            if 'hosts' in info:
                self.manager.updateHosts(info['hosts'])

        self.ecount -= 1
        self.size += 1
        self.pool.append(conn)
        if self.deferred and self.size == self.pool_size:
            self.deferred.callback(self)
            self.deferred = None

        if self.disconnecting:
            conn.transport.loseConnection()
Beispiel #30
0
    def find_one(self,
                 spec=None,
                 fields=None,
                 filter=None,
                 slave_okay=False,
                 _proto=None):
        if isinstance(spec, ObjectId):
            spec = SON(dict(_id=spec))

        cursor = yield self.find(spec,
                                 limit=-1,
                                 fields=fields,
                                 filter=filter,
                                 slave_okay=slave_okay,
                                 _proto=_proto)
        docs = yield cursor.as_list()
        if not docs:
            defer.returnValue(None)

        if isinstance(docs[0], dict) and docs[0].get("err") is not None:
            raise errors.OperationFailure(docs[0])
        defer.returnValue(docs[0])
Beispiel #31
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, True)
    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, True) + _make_c_string(flags)
    if isinstance(value, DBRef):
        return _element_to_bson(key, value.as_doc(), False)
    if isinstance(value, Timestamp):
        inc = struct.pack("<i", value.inc)
        timestamp = struct.pack("<i", value.time)
        return "\x11" + name + inc + timestamp

    raise InvalidDocument("cannot convert value of type %s to bson" %
                          type(value))
Beispiel #32
0
 def rename(self, new_name):
     cmd = SON([("renameCollection", str(self)), ("to", "%s.%s" % \
         (str(self._database), new_name))])
     return self._database("admin")["$cmd"].find_one(cmd)
Beispiel #33
0
 def runCommand(self, command, value, **kwargs):
     '''@see: http://www.mongodb.org/display/DOCS/Commands'''
     cmd = SON([ (command, value) ])
     cmd.update(**kwargs)
     d = self._database["$cmd"].find_one(cmd)
     return d