def searchMetadata(): # Get request data querystr = request.args.get("query") fieldname = request.args.get('fieldName', default=None) # Error out if query or field not provided if not querystr: return api_error(400, "Query string not specified.") if not fieldname: return api_error(400, "Field name to search not specified.") # Search by table matches = search_db(fieldname, querystr) # Log query current_app.logger.info( "{}\t{}\tsearchMetadata\tquery: {}\tfieldname: {}".format( epochalypse_now(), request.cookies.get("user_id"), querystr, fieldname)) # Yield a list of variable names if not matches: rv = jsonify({"matches": []}) else: rv = jsonify({"matches": matches}) resp = make_response(rv) # Set cookie data if not found if not request.cookies.get("user_id"): expire_date = datetime.datetime.now() + datetime.timedelta(days=90) g_uuid = str(uuid.uuid4()) resp.set_cookie("user_id", g_uuid, expires=expire_date) return resp
def selectMetadata(): # Get request data varname = request.args.get("varName") fieldname = request.args.get('fieldName', default=None) # Error out if varname not provided if not varname: return api_error(400, "Variable name not provided.") # Get variable data (abort if not valid) var = session.query(Variable).filter(Variable.name == varname).first() if not var: return api_error(400, "Invalid variable name.") var_data = var.serialize # Append topics topics = session.query(Topic).filter(Topic.name == varname).group_by( Topic.topic).all() umbrellas = session.query(Umbrella).filter( Umbrella.topic.in_([str(t.topic) for t in topics])).all() var_data["topics"] = [{ "umbrella": str(u.umbrella), "topic": str(u.topic) } for u in umbrellas] # Append responses responses = session.query(Response).filter( Response.name == varname).group_by(Response.label).all() var_data["responses"] = { value: label for (value, label) in [(r.value, r.label) for r in responses] } # Error out if field name not valid if fieldname and fieldname not in var_data.keys(): return api_error(400, "Invalid field name.") # Log query current_app.logger.info( "{}\t{}\tselectMetadata\tname: {}\tfield: {}".format( epochalypse_now(), request.cookies.get("user_id"), varname, str(fieldname))) # Return only a single field if specified if not fieldname: rv = jsonify(var_data) else: result = {fieldname: var_data[fieldname]} rv = jsonify(result) resp = make_response(rv) # Set cookie data if not found if not request.cookies.get("user_id"): expire_date = datetime.datetime.now() + datetime.timedelta(days=90) g_uuid = str(uuid.uuid4()) resp.set_cookie("user_id", g_uuid, expires=expire_date) return resp
def _pred(filter): """ Create a SqlAlchemy Binary Expression given a single search criteria. :param filter: A dictionary with keys 'name', 'op' and 'val', indicating the attribute name, comparison operation and the comparison value we wish to use. 'name' can be any supported attribute name of a variable (e.g. 'name'/'data_source'), or one of 'response'/'topic'/'umbrella'. 'op' can be one of 'like','eq','neq','gt','gte','lt','lte' (where the op name corresponds to the usual semantics of these binary comparison operators. Note that specifying 'like' performs a fuzzy (LIKE) query in the database. Corresponding wildcards ('%') must be provided in the 'val' attribute for this to take effect. 'val' is the value we wish to compare against. This is either a string or a numeric, corresponding to the type of the attribute specified by 'name'. Comparison against values work as expected, but comparison against another attribute is not supported. :return: A SqlAlchemy BinaryExpression object corresponding to given search criteria. """ # Note: We may not have a 'val' key (for is_null/is_not_null) name, op, val = filter['name'], filter['op'], filter.get('val') op = op.lower().strip() if name in variable_attrs: column = getattr(Variable, name) elif name == 'response': column = Response.label else: return api_error(400, "Invalid name for search.") if op == 'like': pred = column.like(val) elif op in ('eq', '=='): pred = operator.eq(column, val) elif op in ('neq', 'ne', '!='): pred = operator.ne(column, val) elif op in ('gt', '>'): pred = operator.gt(column, val) elif op in ('gte', 'ge', '>='): pred = operator.ge(column, val) elif op in ('lt', '<'): pred = operator.lt(column, val) elif op in ('lte', 'le', '<='): pred = operator.le(column, val) elif op in ('in', ): pred = column.in_(val) elif op in ('not_in', ): pred = ~column.in_(val) elif op in ('is_null', ): pred = operator.eq(column, None) elif op in ('is_not_null', ): pred = operator.ne(column, None) else: return api_error(400, "Unrecognized operator") return pred
def filterMetadata(): # Get request data fields = request.args.keys() # Error out if no fields provided if not fields: return api_error(400, "Fields to search not provided.") # Construct filter object found = [] for field in fields: for value in request.args.getlist(field): found.extend(search_db(field, value)) # Log query current_app.logger.info("{}\t{}\tfilterMetadata\tfilters: {}".format( epochalypse_now(), request.cookies.get("user_id"), list(request.args.items()))) # Return list of matches if not found: rv = jsonify({"matches": []}) else: varlist = dedupe_varlist(found) rv = jsonify({"matches": varlist}) resp = make_response(rv) # Set cookie data if not found if not request.cookies.get("user_id"): expire_date = datetime.datetime.now() + datetime.timedelta(days=90) g_uuid = str(uuid.uuid4()) resp.set_cookie("user_id", g_uuid, expires=expire_date) return resp
def search(): name = request.args.get('name').lower().strip() val = request.args.get('val') # May contain embedded '%' as wildcard(s) if name in variable_attrs: column = getattr(Variable, name) results = [ v.name for v in session.query(Variable).filter(column.like(val)) ] elif name == 'response': results = [ r.name for r in session.query(Response).filter(Response.label.like(val)) ] elif name == 'topic': results = [ t.name for t in session.query(Topic).filter(Topic.topic.like(val)) ] elif name == 'umbrella': topic_names = [ u.topic_obj.topic for u in session.query(Umbrella).filter( Umbrella.umbrella.like(val)) ] results = [ t.name for t in session.query(Topic).filter(Topic.topic.in_(topic_names)) ] else: return api_error(400, "Invalid name for search.") return jsonify(list(set(results)))
def select(variable_name, attrs=None, as_json=False): """ Return a dictionary of variable attributes, given the variable's name :param variable_name: The name of the variable we're interested in :param attrs: optional, a list of attributes that we're interested in. If unspecified, all attributes of the variable are returned. Unrecognized attributes are ignored. :return: A dictionary with attribute names as the keys, and attribute value as the values. This function raises an AppException if no variable with the given name is found """ obj = session.query(Variable).filter( Variable.name == variable_name).first() if obj: return variable_details(obj, attrs=attrs, as_json=as_json) else: return api_error(400, "Invalid variable name.")
def select(variable_name): obj = session.query(Variable).filter( Variable.name == variable_name).first() if obj: d = dict((attr, getattr(obj, attr, '')) for attr in variable_attrs) # TODO: The following structure is used to maintain compatibility with old behavior # Probably it makes sense to reverse the keys/values d['responses'] = dict((r.value, r.label) for r in obj.responses) # TODO: The following structure is used to maintain compatibility with old behavior # A better structure to this would be to simply return an <umbrella_name>: [<topic_names>] dictionary here d['topics'] = [{ 'umbrella': str(t.umbrella), 'topic': str(t) } for t in obj.topics] keys = list(request.args.keys()) or d.keys() return jsonify(dict((k, d[k]) for k in keys)) else: return api_error(400, "Invalid variable name.")