def find_and_modify(self, query=None, update=None, upsert=False, **kwargs): 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 result = yield from self._database["$cmd"].find_one(cmd) 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')
def find_and_modify(self, query=None, update=None, upsert=False, **kwargs): 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 result = yield from self._database["$cmd"].find_one(cmd) 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')
def map_reduce(self, map, reduce, full_response=False, **kwargs): cmd = SON([("mapreduce", self._collection_name), ("map", map), ("reduce", reduce)]) cmd.update(**kwargs) result = yield from self._database["$cmd"].find_one(cmd) if full_response: return result return result.get("result")
def count(self, spec=None, fields=None): 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)]) result = yield from self._database["$cmd"].find_one(spec) return result["n"]
def create_collection(self, name, options=None): collection = Collection(self, name) if options: if "size" in options: options["size"] = float(options["size"]) command = SON({"create": name}) command.update(options) result = yield from self["$cmd"].find_one(command) if result.get("ok", 0.0): return collection else: raise RuntimeError(result.get("errmsg", "unknown error")) else: return collection
def aggregate(self, pipeline, full_response=False): cmd = SON([("aggregate", self._collection_name), ("pipeline", pipeline)]) result = yield from self._database["$cmd"].find_one(cmd) if full_response: return result return result.get("result")
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)]) result = yield from self._database['$cmd'].find_one(spec) return result.get('md5')
def remove(self, spec, safe=False): if isinstance(spec, ObjectId): spec = SON(dict(_id=spec)) if not isinstance(spec, dict): raise TypeError("spec must be an instance of dict, not %s" % type(spec)) proto = self._database._protocol proto.OP_DELETE(str(self), spec) return (yield from self.__safe_operation(proto, safe))
def distinct(self, key, spec=None): cmd = SON([("distinct", self._collection_name), ("key", key)]) if spec: cmd["query"] = spec result = yield from self._database["$cmd"].find_one(cmd) if result: return result.get("values") return {}
def drop_index(self, index_identifier): if isinstance(index_identifier, str): 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 (yield from self._database["$cmd"].find_one(cmd))
def create_index(self, sort_fields, **kwargs): 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) yield from self._database.system.indexes.insert(index, safe=True) return name
def authenticate_with_nonce(self, result, name, password): nonce = result['nonce'] key = auth._auth_key(nonce, name, password) # hacky because order matters auth_command = SON(authenticate=1) auth_command['user'] = name auth_command['nonce'] = nonce auth_command['key'] = key # Now actually authenticate result = yield from self["$cmd"].find_one(auth_command) return self.authenticated(result)
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, dict): raise TypeError("spec must be an instance of dict") if fields is not None and not isinstance(fields, (dict, list)): raise TypeError("fields must be an instance of dict or list") 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 fields is not None: if not isinstance(fields, dict): 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, tuple) 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._protocol else: proto = _proto return (yield from proto.OP_QUERY(str(self), spec, skip, limit, fields))
def find_one(self, spec=None, fields=None, _proto=None): if isinstance(spec, ObjectId): spec = SON(dict(_id=spec)) docs = yield from self.find(spec, limit=-1, fields=fields, _proto=_proto) doc = docs and docs[0] or {} if doc.get("err") is not None: if doc.get("code") == 11000: raise errors.DuplicateKeyError else: raise errors.OperationFailure(doc) else: return doc
def create_index(self, sort_fields, **kwargs): 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) yield from self._database.system.indexes.insert(index, safe=True) return name
def rename(self, new_name): cmd = SON([("renameCollection", str(self)), ("to", "%s.%s" % \ (str(self._database), new_name))]) return (yield from self._database("admin")["$cmd"].find_one(cmd))