def get_files(self, ids, servers_known = False, bl = 0): ''' Devuelve los datos de los ficheros correspondientes a los ids dados en formato hexadecimal. @param ids: Lista de identificadores de los ficheros a recuperar. Si server_known es False, es una lista de cadenas. Si server_known es True, es una lista de tuplas, que incluyen el identificador del fichero y el número de servidor. @param servers_known: Indica si la lista de identificadores incluye el servidor donde se encuentra el fichero. @type bl: int o None @param bl: valor de bl para buscar, None para no restringir @rtype generator @return Generador con los documentos de ficheros ''' if len(ids) == 0: return () sids = defaultdict(list) # si conoce los servidores en los que están los ficheros, # se analiza ids como un iterable (id, servidor, ...) # y evitamos buscar los servidores if servers_known: for x in ids: sids[x[1]].append(hex2mid(x[0])) else: # averigua en qué servidor está cada fichero nindir = self.server_conn.foofind.indir.find({"_id": {"$in": [hex2mid(fid) for fid in ids]}}) for ind in nindir: if "t" in ind: # si apunta a otro id, lo busca en vez del id dado sids[ind["s"]].append(ind["t"]) else: sids[ind["s"]].append(ind["_id"]) self.server_conn.end_request() if len(sids) == 0: # Si no hay servidores, no hay ficheros return tuple() elif len(sids) == 1: # Si todos los ficheros pertenecen al mismo servidor, evita MultiAsync sid = sids.keys()[0] if not "conn" in self.servers_conn[sid]: return () conn = self.servers_conn[sid]["conn"] return end_request( conn.foofind.foo.find( {"_id":{"$in": sids[sid]}} if bl is None else {"_id":{"$in": sids[sid]},"bl":bl})) # función que recupera ficheros def get_server_files(async, sid, ids): ''' Recupera los datos de los ficheros con los ids dados del servidor mongo indicado por sid y los devuelve a través del objeto async. ''' if not "conn" in self.servers_conn[sid]: return conn = self.servers_conn[sid]["conn"] async.return_value(end_request(conn.foofind.foo.find( {"_id": {"$in": ids}} if bl is None else {"_id": {"$in": ids},"bl":bl})))
def get_sources_groups(self): ''' Obtiene los grupos de los orígenes @return set de grupos de orígenes ''' return set(j for i in end_request(self.server_conn.foofind.source.find()) if "g" in i for j in i["g"])
def get_image_server(self,server): ''' Obtiene el servidor que contiene una imagen ''' return end_request( self.server_conn.foofind.serverImage.find_one({"_id":server}), self.server_conn)
def get_sources(self, skip=None, limit=None, blocked=False, group=None, must_contain_all=False): ''' Obtiene los orígenes como generador @type skip: int @param skip: número de elementos omitidos al inicio, None por defecto. @type limit: int @param limit: número de elementos máximos que obtener, None por defecto para todos. @type blocked: bool o None @param blocked: retornar elementos ya procesados, None para obtenerlos todos, False por defecto. @type group: basestring, iterable o None @param group: basestring para un grupo, si es None, para todos @type must_contain_all: bool @param must_contain_all: False para encontrar todos los que contengan alguno de los grupos de group, True para encontrar los que contengan todos los groups de group. @rtype: MongoDB cursor @return: cursor con resultados ''' query = {} if blocked == True: query["crbl"] = 1 elif blocked == False: query["$or"] = {"crbl": { "$exists" : False } }, {"crbl":0} if not group is None: if isinstance(group, basestring): query["g"] = group elif must_contain_all: query["g"] = {"$all": group} else: query["g"] = {"$in": group} sources = self.server_conn.foofind.source.find(query).sort("d") if not skip is None: sources.skip(skip) if not limit is None: sources.limit(limit) return list(end_request(sources))
def count_sources(self, blocked=False, group=None, must_contain_all=False, limit=None): ''' Obtiene el número de orígenes @type blocked: bool o None @param blocked: retornar elementos ya procesados, None para obtenerlos todos, False por defecto. @type group: basestring, iterable o None @param group: basestring para un grupo, si es None, para todos @type must_contain_all: bool @param must_contain_all: False para encontrar todos los que contengan alguno de los grupos de group, True para encontrar los que contengan todos los groups de group. @rtype integer @return Número de orígenes ''' query = {} if limit is None else {"limit":limit} if blocked == True: query["crbl"] = 1 elif blocked == False: query["$or"] = {"crbl": { "$exists" : False } }, {"crbl":0} if not group is None: if isinstance(group, basestring): query["g"] = group elif must_contain_all: query["g"] = {"$all": group} else: query["g"] = {"$in": group} return end_request(self.server_conn.foofind.source.find(query).count(True), self.server_conn)
def get_file_vote(self,file_id,user,lang): ''' Recupera el voto de un usuario para un archivo ''' return end_request( self.user_conn.foofind.vote.find_one({"_id":"%s_%s"%(file_id,user.id),"l":lang}), self.user_conn)
def set_file_vote(self,file_id,user,lang,vote): ''' Guarda el voto en la colección y actualiza el archivo correspondiente con los nuevos datos ''' self.user_conn.foofind.vote.save({"_id":"%s_%s"%(file_id,user.id),"u":hex2mid(user.id),"k":user.karma if vote==1 else -user.karma,"d":datetime.utcnow(),"l":lang}) #para cada idioma guarda el karma, la cuenta total y la suma map_function=Code(''' function() { emit(this.l,{ k:this.k, c:new Array((this.k>0)?1:0,(this.k<0)?1:0), s:new Array((this.k>0)?this.k:0,(this.k<0)?this.k:0) }) }''') #suma todo y aplica la funcion 1/1+E^(-X) para que el valor este entre 0 y 1 reduce_function=Code(''' function(lang, vals) { c=new Array(0,0); s=new Array(0,0); for (var i in vals) { c[0]+=vals[i].c[0]; c[1]+=vals[i].c[1]; s[0]+=vals[i].s[0]; s[1]+=vals[i].s[1]; } return {t:1/(1+Math.exp(-((s[0]*c[0]+s[1]*c[1])/(c[0]+c[1])))), c:c, s:s}; }''') #tercer parametro para devolverlo en vez de generar una coleccion nueva votes=self.user_conn.foofind.vote.map_reduce(map_function,reduce_function,{"inline":1},query={'_id':{'$regex':"^%s"%file_id}}) #devolver un diccionario de la forma idioma:valores return end_request({values["_id"]:values["value"] for values in votes["results"]}, self.user_conn)
def get_file(self, fid, sid=None, bl=0): ''' Obtiene un fichero del servidor @type fid: str @param fid: id de fichero en hexadecimal @type sid: str @param sid: id del servidor @type bl: int o None @param bl: valor de bl para buscar, None para no restringir @rtype mongodb document @return Documento del fichero ''' mfid = hex2mid(fid) if sid is None: # averigua en qué servidor está el fichero ind = self.server_conn.foofind.indir.find_one({"_id":mfid}) if ind is None: return None if "t" in ind: mfid = ind["t"] sid = ind["s"] self.server_conn.end_request() if not "conn" in self.servers_conn[sid]: return None conn = self.servers_conn[sid]["conn"] return end_request(conn.foofind.foo.find_one( {"_id":mfid} if bl is None else {"_id":mfid,"bl":bl}), conn)
def get_file_comments_sum(self,file_id): ''' Cuenta los comentarios que hay para cada idioma ''' return end_request({ lang["l"]:lang["c"] for lang in self.user_conn.foofind.comment.group({"l":1},{'f':hex2mid(file_id)},{"c":0},Code("function(o,p){p.c++}"))}, self.user_conn)
def get_server_stats(self, server): ''' Obtiene las estadisticas del servidor ''' return end_request( self.server_conn.foofind.search_stats.find_one({"_id":server}), self.server_conn)
def create_user(self,data): ''' Guarda los datos del usuario. @param data: Diccionario con los datos del usuario a guardar. ''' return end_request(self.user_conn.foofind.users.insert({"username":data["username"],"email":data["email"],"password":sha256(data["password"]).hexdigest(),"karma":0.2,"token":data["token"],"created": datetime.utcnow()}),self.user_conn)
def get_last_files(self): ''' Cuenta los ficheros totales indexados ''' if not "conn" in self.servers_conn[self.current_server]: return () conn = self.servers_conn[self.current_server]["conn"] return end_request( conn.foofind.foo.find({"bl":0}).sort([("$natural",-1)]).limit(25))
def get_last_files(self, n=25): ''' Obtiene los últimos 25 ficheros indexados ''' with self.current_server.context as context: return end_request( tuple(context.conn.foofind.foo.find({"bl":0}).sort([("$natural",-1)]).limit(n)), context.conn)
def get_complaint(self, hexid): ''' Obtiene la información de un enlace reportado @type hexid: str @param hexid: cadena id de MongoDB en hexadecimal @rtype: MongoDB document or None @return: resultado ''' return end_request(self.pages_conn.foofind.complaint.find_one({"_id":hex2mid(hexid)}), self.pages_conn)
def set_file_comment(self,file_id,user,lang,comment): ''' Guarda un comentario de un archivo ''' return end_request( self.user_conn.foofind.comment.insert({ "_id": "%s_%s" % (user.id,int(time())), "f": file_id, "l": lang, "d": datetime.utcnow(), "k": user.karma, "t": comment}), self.user_conn)
def count_complaints(self, processed=False, limit=0): ''' Obtiene el número de enlaces reportados @type processed: bool or None @param processed: Contabilizar las peticiones procesadas, sin procesar o ambas, según sea True, False o None. @rtype integer @return Número de enlaces reportados ''' return end_request(self.pages_conn.foofind.complaint.find( None if processed is None else {"processed":processed}, limit=limit ).count(True), self.pages_conn)
def get_translation(self, hexid): ''' Obtiene la información de una traducción @type hexid: str @param hexid: cadena id de MongoDB en hexadecimal @rtype: MongoDB document or None @return: resultado ''' return end_request( self.pages_conn.foofind.translation.find_one({"_id":hex2mid(hexid)}), self.pages_conn)
def get_source_by_id(self, source): ''' Obtiene un origen a través del id @type source: int o float @param source: identificador del source @rtype dict o None @return origen o None ''' return end_request( self.server_conn.foofind.source.find_one({"_id":source}), self.server_conn)
def get_translations(self, skip=None, limit=None, processed=False): ''' Retorna las traducciones @type skip: int @param skip: número de elementos omitidos al inicio, None por defecto. @type limit: int @param limit: número de elementos máximos que obtener, None por defecto para todos. @type processed: bool @param processed: retornar elementos ya procesados, None para obtenerlos todos, False por defecto. @rtype: MongoDB cursor @return: cursor con resultados ''' translations = self.pages_conn.foofind.translation.find(None if processed is None else {"processed":processed}).sort("created",-1) if not skip is None: translations.skip(skip) if not limit is None: translations.limit(limit) return end_request(translations)
def get_complaints(self, skip=None, limit=None, processed=False): ''' Obtiene los enlaces reportados como generador @type skip: int @param skip: número de elementos omitidos al inicio, None por defecto. @type limit: int @param limit: número de elementos máximos que obtener, None por defecto para todos. @type processed: bool o None @param processed: retornar elementos ya procesados, None para obtenerlos todos, False por defecto. @rtype: MongoDB cursor @return: cursor con resultados ''' complaints = self.pages_conn.foofind.complaint.find(None if processed is None else {"processed":processed}).sort("created",-1) if not skip is None: complaints.skip(skip) if not limit is None: complaints.limit(limit) return end_request(complaints)
def get_file_comment_votes(self,file_id): ''' Recuper los votos de los comentarios de un archivo ''' return end_request(self.user_conn.foofind.comment_vote.find({"f":hex2mid(file_id)}))
def get_file_comments(self,file_id,lang): ''' Recupera los comentarios de un archivo ''' return end_request(self.user_conn.foofind.comment.find({"f":hex2mid(file_id),"l":lang}))
def get_servers(self): ''' Obtiene informacion de los servidores de datos ''' return list(end_request(self.server_conn.foofind.server.find(), self.server_conn))
def count_files(self): ''' Cuenta los ficheros totales indexados ''' count = self.server_conn.foofind.server.group(None, None, {"c":0}, "function(o,p) { p.c += o.c; }") return end_request(count[0]['c'] if count else 0, self.server_conn)
def __search(self,data): ''' Busqueda por los campos que se reciban ''' return end_request(self.user_conn.foofind.users.find_one(data), self.user_conn)
def find_username_start_with(self,username): ''' Busca por un nombre de usuario ''' return end_request( self.user_conn.foofind.users.find({"username":{'$regex':'^'+username+'(_\\d+)?$'}}))
def get_profile_info(self, start): return end_request(self.feedback_conn.foofind.profiler.find({"_date":{"$gt":start}}))